완벽한 회문


25

당신의 임무는 문자열이 얼마나 완벽한 회문을 결정하는 것입니다. 전형적인 회문 (예 : 12321)은 완벽한 회문입니다. 완벽 함은 1입니다.

문자열의 완성도를 결정하기 위해 각 섹션이 회 문인 부분으로 분할 할 수있는 섹션 수를 확인할 수 있습니다. with와 같이 애매 모호한 부분이있는 경우 or 또는 or 또는 aaaa로 분할 할 수 있는 가장 짧은 세트가 재정의되어 가장 짧은 세트 의 길이 인 1의 점수를 얻습니다.[aa, aa][aaaa][a, aaa][aaa, a]aaaa

따라서 비어 있지 않은 입력을 하나만 사용하여 얼마나 완벽한 지 출력하는 프로그램이나 함수를 작성해야합니다 (가장 짧은 세트의 길이는 세트의 각 요소가 회문으로 분할 될 수 있음).

예 :

1111 -> 1 [1111]
abcb -> 2 [a, bcb]
abcbd -> 3 [a, bcb, d]
abcde -> 5 [a, b, c, d, e]
66a -> 2 [66, a]
abcba-> 1 [abcba]
x -> 1 [x]
ababacab -> 2 [aba, bacab]
bacababa -> 2 [bacab, aba]
26600 -> 3 [2, 66, 00] [my user id] [who has a more perfect user id?]
ababacabBACABABA -> 4 [aba, bacab, BACAB, ABA]

예제에서 대괄호 안에있는 것은 출력의 일부가 아니어야합니다.


빈 문자열이 유효한 입력입니까? 그렇다면 출력은 무엇입니까?
Zgarb

8
ababacab그리고 그 반대는 bacababa좋은 테스트 사례 인 것 같습니다.
Neil

선형 시간 알고리즘이 가능한지 여부에 대한 좋은 주장뿐만 아니라 @Neil.
Leaky Nun

@Zgarb 빈 문자열은 유효하지 않은 입력입니다.
Okx

ababacabBACABABA또한 좋은 테스트 사례입니다 (일부 답변은 실패합니다).
Zgarb

답변:


14

Brachylog , 7 바이트

~cL↔ᵐLl

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

설명

~cL          Deconcatenate the input into L
  L↔ᵐL       Reversing all elements of L results in L
     Ll      Output = length(L)

내 첫 번째 게시물에 나를 이겼다. lol
Leaky Nun

7
@LeakyNun 나는 당신이 그것을 시도 할 줄 알았습니다. 지난 몇 달 동안 느슨해 져서 몇 시간을 기다릴 수있게 되었으니 지금은 다시 답장을 보내야합니다!
Fatalize

9

젤리 , 13 12 11 바이트

ŒṖLÞŒḂ € P $ ÐfḢL 
ŒṖLÞṚ € ⁼ $ ÐfḢL
ŒṖṚ € ⁼ $ ÐfL € Ṃ
ŒṖ 파티션 확보
      파티션을위한 필터
  각 하위 파티션을 취소 한 후 Ṛ €
    ⁼는 파티션과 같습니다
        성공적인 각 파티션의 L € 길이
          Ṃ 최소

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

명세서

  • 입력 : "ababacab"(인수로서)
  • 산출: 2

3
@Okx 잘 당신은 그들을 탈출해야합니다.
Leaky Nun

2
글쎄, 백 슬래시를 받아 들일 수 없다면 그것이 유효하지 않다고 생각합니다.
Okx

14
@Okx 문자열을 쓰는 것과 같습니다. 예를 들어 C 프로그램은 문자열 입력과 함께 작동 할 것으로 기대할 수 없습니다 "\".
Conor O'Brien

2
그건 그렇고, 다시 오신 것을 환영합니다. :-)
Arnauld

2
슬프게도 이것은 다른 답변 ababacab과 그 반대의 결과를 제공 bacababa합니다.
Neil

6

Pyth, 9 바이트

lh_I#I#./

테스트 스위트

이것은 가장 짧은 것부터 가장 긴 것까지 모든 입력 파티션을 형성합니다. 그런 다음 반전시 불일치 요소를 필터링하여 불일치시 해당 파티션을 필터링합니다. 마지막으로, 필터링 된 파티션 목록의 첫 번째 요소를 가져 와서 길이를 반환합니다.

그 복잡한 단계를 설명하기 위해 반전에서 불변으로 시작합시다 _I. 반전이 값을 변경하는지 여부를 확인하기 때문에 입력이 회문인지 여부를 확인합니다.

다음으로 회 문성 필터링 : _I#. 이것은 목록의 회문 요소 만 유지합니다.

다음으로 우리는 palindromicity에 대한 필터링에서 불변성을 검사합니다 _I#I. 목록의 모든 요소가 회문 인 경우에만 이것이 진실입니다.

마지막으로 목록의 모든 요소가 회 문인 목록을 필터링합니다 _I#I#.


배울 점이 많습니다 ...
Leaky Nun

6

하스켈 , 83 바이트

f s=minimum[length x|x<-words.concat<$>mapM(\c->[[c],c:" "])s,all((==)=<<reverse)x]

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

이것은 문자열 파티션을 생성하기 위해 Zgarb의 훌륭한 팁을 사용 합니다 .

f s = minimum[                               -- take the minimum of the list
    length x |                               -- of the number of partitions in x
    x<-words.concat<$>mapM(\c->[[c],c:" "])s -- where x are all partitions of the input string s
    , all((==)=<<reverse)x                   -- where each partition is a palindrome.
]

1
와우! 이것은 내 마음을 불었다! 나는 확실히 배울 것이 많다.
maple_shaft

5

클로저, 111 바이트

(defn f[s](if(=()s)0(+(apply min(for[i(range(count s))[a b][(split-at(inc i)s)]:when(=(reverse a)a)](f b)))1)))

가능한 모든 위치에서 분할하고 첫 번째 부분이 회 문인 경우 나머지 문자열에 대한 분할을 찾습니다.

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

Ungolfed는 thread-last macro를 사용 ->> 합니다.

(defn f [s]
  (if (empty? s)
    0
    (let [results (for[i (range(count s))]
                      (let [[a b] (split-at (inc i) s)]
                         (when (= a (reverse a))
                           (f b))))]
      (->> results        ; Take results (a list of integers and nils),
           (filter some?) ; remove null values (they occur when "a" is not a palindrome)
           (apply min)    ; find the minium value,
           inc))))        ; and increment by one.

불분명 한 버전은 다음과 같은 코드를 작성하지 마십시오 .D

(defn f [s]
   (->> (f b)
        (when (= a (reverse a)))
        (let [[a b] (split-at (inc i) s)])
        (for[i (range(count s))])
        (filter some?)
        (apply min)
        inc
        (if (empty? s) 0)))

겠습니까 이 팁 도움? 클로저를 전혀 몰라요.
Leaky Nun

일반적으로 예, 그러나이 경우 함수 f는 for : 내에서 자체를 호출해야합니다 (f b). 테일 콜 위치에서을 사용할 수 있습니다 recur.
NikoNyrh

여전히 기능으로 교체 defn하고 사용할 수 있습니다 fn.
cliffroot

(fn f[s]( ... ))? 아 맞다 당신은 그것으로 2 문자를 저장합니다.
NikoNyrh

5

자바 스크립트 (ES6) 143 126 124 바이트

Neil 덕분에 2 바이트 절약

NikoNyrh 방법에서 영감을 얻었습니다 .

s=>(r=1/0,F=(s,i=1,p=0)=>s[p++]?([...o=s.slice(0,p)].reverse().join``==o&&(s[p]?F(s.slice(p),i+1):r=r<i?r:i),F(s,i,p)):r)(s)

형식화 및 의견

s => (                          // given a string 's':
  r = 1 / 0,                    // 'r' = best score, initialized to +Infinity
  F = (                         // 'F' is a recursive function that takes:
    s,                          //   - the current string 's'
    i = 1,                      //   - a substring counter 'i'
    p = 0                       //   - a character pointer 'p'
  ) =>                          //
    s[p++] ? (                  // if we haven't reached the end of the string:
      [...o = s.slice(0, p)]    //   compute 'o' = substring of length 'p'
      .reverse().join`` == o    //   if 'o' is a palindrome,
      && (                      //   then:
        s[p] ?                  //     if there are still characters to process:
          F(s.slice(p), i + 1)  //       do a recursive call on the remaining part
        :                       //     else:
          r = r < i ? r : i     //       update the score with r = min(r, i)
      ),                        //   in all cases:
      F(s, i, p)                //     do a recursive call with a longer substring
    ) :                         // else:
      r                         //   return the final score
  )(s)                          // initial call to F()

테스트 사례


초기 접근 방식, 173 168 바이트

입력 문자열의 모든 가능한 파티션을 계산하는 꽤 긴 재귀 함수입니다.

f=(s,b=1/(k=0))=>++k>>(L=s.length)?b:f(s,(k|1<<30).toString(2).slice(-L).match(/(.)\1*/g).some(m=>[...o=s.slice(i,i+=m.length)].reverse(n++).join``!=o,n=i=0)?b:b<n?b:n)

형식화 및 의견

f = (                           // given:
  s,                            //   - a string 's'
  b = 1 / (k = 0)               //   - a best score 'b' (initialized to +Infinity)
) =>                            //   - a counter 'k' (initialized to 0)
  ++k >> (L = s.length) ?       // if 'k' is greater or equal to 2^(s.length):
    b                           //   stop recursion and return 'b'
  :                             // else:
    f(                          //   do a recursive call:
      s,                        //     using the same string 's'
      (k | 1 << 30)             //     compute an array containing the groups of identical
      .toString(2).slice(-L)    //     digits in the binary representation of 'k', padded
      .match(/(.)\1*/g)         //     with leading zeros and cut to the length of 's'
      .some(g =>                //     for each group 'g' in this array:
        [... o = s.slice(       //       compute 'o' = corresponding substring of 's',
          i, i += g.length      //       starting at position 'i' with the same length
        )]                      //       (e.g. s = 'abcd' / k = 0b1101 => 'ab','c','d')
        .reverse(n++)           //       increment the number of groups 'n'
        .join`` != o,           //       return true if this substring is NOT a palindrome
        n = i = 0               //       initialize 'n' and 'i'
      ) ?                       //     if some() returns true:
        b                       //       invalid partition -> keep the previous score 'b'
      :                         //     else:
        b < n ? b : n           //       valid partition -> use min(b, n)
    )                           //   end of recursive call

테스트 사례


설명을 올바르게 이해했다면 ,p=0, s[p++]?및을 사용하여 몇 바이트를 저장할 수 있습니다 ,F(s,i,p).
Neil

@Neil 예. :-)
Arnauld

5

젤리 , 10 바이트

ŒṖŒḂ€¬$ÞḢL

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

방법?

사실 사용
[0]<[0,0]<[0,0,0],...,<[0,...,0,1]<...
의 핵심으로 우리 종류의 파티션은 "각 부분에 대한 상동 아니다"따라서 경우 첫 번째 항목은 모든 상동 최소 길이 될 것이다 -.

참고 : 길이가 1 인 문자열은 모두 회문 식이므로 길이가 n 인 비어 있지 않은 문자열 은 항상 n이 0 인 키가 됩니다 .

ŒṖŒḂ€¬$ÞḢL - Main link: s             e.g. 'abab'
ŒṖ         - partitions of s               [['a','b','a','b'],['a','b','ab'],['a','ba','b'],['a','bab'],['ab','a','b'],['ab','ab'],['aba','b'],['abab']]
       Þ   - sort by (create the following key and sort the partitions by it):
      $    -   last two links as a monad:  (key evaluations aligned with above:)
  ŒḂ€      -     is palindromic? for €ach   [ 1 , 1 , 1 , 1 ] [ 1 , 1 , 0  ] [ 1 , 0  , 1 ] [ 1 , 1   ] [ 0  , 1 , 1 ] [ 0  , 0  ] [ 1   , 1 ] [ 0    ] 
     ¬     -     not                        [ 0 , 0 , 0 , 0 ] [ 0 , 0 , 1  ] [ 0 , 1  , 0 ] [ 0 , 0   ] [ 1  , 0 , 0 ] [ 1  , 1  ] [ 0   , 0 ] [ 1    ]
           - ...i.e.:         
           -       making the sorted keys: [[ 0 , 0   ],[ 0   , 0 ],[ 0 , 0 , 0 , 0 ],[ 0 , 0 , 1  ],[ 0 , 1  , 0 ],[ 1    ],[ 1  , 0 , 0 ],[ 1  , 1  ]]
           -  hence the sorted partitions: [['a','bab'],['aba','b'],['a','b','a','b'],['a','b','ab'],['a','ba','b'],['abab'],['ab','a','b'],['ab','ab']]
        Ḣ  - head of the result             ['a','bab']
         L - length                         2

5

하스켈 , 69 바이트

x!(a:b)|p<-a:x=p!b++[1+f b|p==reverse p]
x!y=[0|x==y]
f=minimum.(""!)

함수를 정의합니다 f. 온라인으로 사용해보십시오!

설명

삽입 도우미 함수 x ! y는 정수 목록을 계산합니다. 정수 목록은 그대로 reverse x ++ y둔 회문으로 분할되는 길이입니다 reverse x. y비어 있지 않은 경우 최소 분할 길이를 포함해야합니다 . 작동 방식은 이렇습니다.

  • y비어 있지 않으면 문자가 튀어 나와로 푸시됩니다 x. 경우 x회문이되고, 우리는 메인 함수를 호출 f의 꼬리 y와에 대한 계정에 1을 추가합니다 x. 또한, 우리는 전화 !새에 xy잠재적 인 분할을 놓치지 않을 수 있습니다.
  • 경우 y비어, 우리는 반환 [0](길이 0의 한 분할) 경우 x도 빈 없으며, [](더 쪼갠이) 그렇지.

메인 함수는 f단지 호출 "" ! x하고 최소한의 결과를 취합니다.

x!(a:b)|          -- Function ! on inputs x and list with head a and tail b,
  p<-a:x=         -- where p is the list a:x, is
  p!b++           -- the numbers in p!b, and
  [1+f b|         -- 1 + f b,
   p==reverse p]  -- but only if p is a palindrome.
x!y=              -- Function ! on inputs x and (empty) list y is
  [0|             -- 0,
   x==y]          -- but only if x is also empty.
f=                -- Function f is:
  minimum.(""!)   -- evaluate ! on empty string and input, then take minimum.

3

JavaScript (Firefox 30-57), 97 바이트

f=(s,t=``,i=0)=>s?Math.min(...(for(c of s)if([...t+=c].reverse(++i).join``==t)1+f(s.slice(i)))):0

ES6 포트 :

f=(s,t=``)=>s?Math.min(...[...s].map((c,i)=>[...t+=c].reverse().join``==t?1+f(s.slice(i+1)):1/0)):0
<input oninput=o.textContent=f(this.value)><pre id=o>

나는 내가 잊어 버린 것으로 생각하는 간단한 해결책처럼 보이지만 적어도 모든 테스트 사례를 통과합니다.


1

하스켈, 139 (116) 109 바이트

h[]=[[]]
h x=words.concat<$>mapM(\c->[[c],c:" "])x
r x=reverse x==x
g x=minimum[length y|y<-h x,and$r<$>y]

Haskell golfing에서 여전히 녹색이지만 여기에 내가 빨리 시도 할 수있는 최선의 시도가 있습니다.

  • h는 문자열과 같이 List의 가능한 모든 연속 하위 시퀀스의 List를 만드는 함수입니다. 입력 문자열을 가져 와서 g로 나눕니다.
  • r은 List가 회 문인 경우에 대한 부울을 반환하는 간단한 함수입니다.
  • g는 입력 목록을 가져오고 연속 된 하위 시퀀스 가능성 목록을 얻기 위해 h를 호출 (and.map r)하고 회문을 포함하지 않는 하위 목록을 제거하기 위해 필터를 적용하는 주요 함수 이며, 그 지점에서 길이는 목록에 적용됩니다. 우리는 정답 인 머리를 잡을 수 있도록 분류되었습니다.

나는 더 나은 대답이 응용 프로그램을 사용하여 Haskell에있는 목록의 비 결정적 특성을 활용할 수 있다고 생각했습니다. Control.Applicative를 가져와야하는 경우에도 응용 프로그램을 사용하여 함수 h에서 많은 바이트를 줄일 수 있습니다. 개선에 대한 의견은 환영합니다.

업데이트 1

Laikoni의 최소 기능에 대한 알림을 기반으로 한 엄청난 비용 절감. sort를 제거하면 실제로 Prelude!에서 최소값이 정의되어 있기 때문에 Data.List 가져 오기를 삭제할 수있었습니다.

업데이트 2

목록 이해를 filter.map의 유용한 대체물로 사용하는 것에 대한 nimi의 제안 덕분에. 그것은 몇 바이트를 절약했습니다. 또한 Laikonis 답변에서 깔끔한 문자열 파티션 트릭을 빌려서 몇 바이트도 저장했습니다.


1
h []=[[]]h (x:y)=map ([x]:)불필요한 공백이 포함되어 있습니다. head.sort입니다 minimum.
Laikoni

@Laikoni 감사합니다! 컴퓨터로 돌아 오면 업데이트하겠습니다!
maple_shaft

1
리스트 이해력은 종종 filter& map: 보다 짧습니다 g x=head$sort[length y|y<-h x,and$r<$>y].
nimi

@nimi 감사합니다. Haskell에는 유용한 골프 팁이 많이 있습니다. 나는 매번 새로운 트릭을 배웁니다.
maple_shaft

1

PHP, 319 바이트

for(;$i<$l=strlen($s=$argn);$i++)for($j=$l-$i;$j;$j--)strrev($r=substr($s,$i,$j))!=$r?:$e[+$i][]=$r;uasort($e,function($a,$b){return strlen($b[0])<=>strlen($a[0])?:count($a)<=>count($b);});foreach($e as$p=>$v)foreach($v as$w){$s=preg_replace("#^(.{{$p}})$w#","$1".str_pad("",strlen($w),"ö"),$s,1,$c);!$c?:++$d;}echo$d;

온라인 버전

넓히는

for(;$i<$l=strlen($s=$argn);$i++)
for($j=$l-$i;$j;$j--)strrev($r=substr($s,$i,$j))!=$r?:$e[+$i][]=$r; #Make all substrings that are palindromes for each position
uasort($e,function($a,$b){return strlen($b[0])<=>strlen($a[0])?:count($a)<=>count($b);}); # sort palindrome list high strlen lowest count for each position
foreach($e as$p=>$v)
foreach($v as$w){
    $s=preg_replace("#^(.{{$p}})$w#","$1".str_pad("",strlen($w),"ö"),$s,1,$c);
    !$c?:++$d; # raise count
}
echo$d; # Output

E_NOTICE가없는 긴 버전으로 결과 배열을 출력


이에 대한 잘못된 결과를 제공하는 것ababacabBACABABA
Zgarb

@Zgarb 이제 작동합니다
Jörg Hülsermann
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.