Mükemmel Palindromlar


25

Senin görevin bir dize ne kadar mükemmel bir palindrom olduğunu belirlemek. Tipik palindromunuz (örneğin, 12321) mükemmel bir palindromdur; mükemmelliği 1.

Bir dizgenin kusursuzluğunu belirlemek için, onu her bir bölümün bir palindrom olduğu yere kaç bölüme ayırabileceğinizi görürsünüz. Eğer ya da ya da ya da ya da ya da aaaagibi ayrılabildiğiniz gibi belirsizlikler varsa , en kısa küme, en kısa kümenin uzunluğu olan 1 puan vererek geçersiz kılınır .[aa, aa][aaaa][a, aaa][aaa, a]aaaa

Bu nedenle, boş olmayan bir girdi alan ve ne kadar mükemmel çıktılar çıkaran bir program veya işlev yazmalısınız (bu, kümedeki her öğenin bir palindrom olduğu yere bölediğiniz en kısa kümenin uzunluğu).

Örnekler:

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]

Örneklerde köşeli parantez içindeki hiçbir şey çıktının bir parçası olmamalıdır.


Boş dize geçerli bir girdi mi ve eğer öyleyse, çıktı ne olmalıdır?
Zgarb

8
ababacabve bunun tersi, bacababaiyi test durumları gibi görünüyor.
Neil

@ Neil gibi doğrusal zaman algoritmasının mümkün olup olmadığı konusunda iyi argümanlar.
Leaky Nun

@Zgarb Boş dize geçerli bir giriş değil.
Okx

ababacabBACABABAAynı zamanda iyi bir test durumudur (bazı cevaplar üzerinde başarısız).
Zgarb

Yanıtlar:


14

Brachylog , 7 bayt

~cL↔ᵐLl

Çevrimiçi deneyin!

açıklama

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

Sen beni yendi ... ilk
yazımda

7
@LeakyNun Bunu deneyeceğini biliyordum. Geçen aylar gevşeyip birkaç saat bekleyebilirdim, şimdi yanınızda derhal cevap vermek zorundayım!
17'de

9

Jöle , 13 12 11 bayt

ÞŒḂLÞŒḂ € P $ ÐfḢL 
ŒṖLÞṚ € ⁼ $ ÐfḢL
ŒṖṚ € ⁼ $ DFL € m
ŒṖ bölümleri almak
      Filterf bölümler için filtre
  Sub € her alt bölümün tersine çevrilmesinden sonra
    ⁼ bölüme eşittir
        L € her başarılı bölümün uzunluğu
          Ṃ minimum

Çevrimiçi deneyin!

gözlük

  • Giriş: "ababacab"(bağımsız değişken olarak)
  • Çıktı: 2

3
@Okx peki onlardan kaçmak zorunda kalacaksınız.
Leaky Nun

2
Ters eğik çizgileri kabul edemezse bunun geçerli olduğunu sanmıyorum.
Okx

14
@Okx Bir dize yazmak gibi. Diyelim ki, bir C programının bir dizge girişiyle çalışmasını bekleyemezsiniz "\", çünkü bu geçersiz sözdizimi.
Conor O'Brien,

2
Bu arada tekrar hoşgeldiniz. :-)
Arnauld

2
Ne yazık ki bu farklı cevaplar veriyor ababacabve bunun tersi bacababa.
Neil

6

Pyth, 9 bayt

lh_I#I#./

Test odası

Bu, girişin en kısa bölümünden en uzun bölüme kadar olan tüm bölümlerini oluşturur. Daha sonra, bu bölümleri değişmezlik altında değişmezlik altındaki öğeleri süzme altında filtreler. Son olarak, filtrelenmiş bölümler listesinin ilk öğesini alıyoruz ve uzunluğunu döndürüyoruz.

Bu karmaşık adımı açıklamak için, tersine dönüşünün altında değişmezliği başlayalım: _I. Bu, girişinin bir palindrom olup olmadığını kontrol eder, çünkü ters çevirmenin değeri değiştirip değiştirmediğini kontrol eder.

Daha sonra, palindromicity için filtreleme: _I#. Bu, listenin yalnızca palindromik öğelerini koruyacaktır.

Sonra, palindromicity için filtreleme altında değişmezliği kontrol edin: _I#I. Bu, listenin tüm öğelerinin palindrom olması durumunda ve yalnızca doğrudur.

Son olarak, biz listenin bütün elemanları palindromes olan listeler için filtre: _I#I#.


Öğrenmem gereken çok şey var ...
Leaky Nun

6

Haskell , 83 bayt

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

Çevrimiçi deneyin!

Bu Zgarb'ın string bölümleri oluşturmak için mükemmel ipucunu kullanır .

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
Vaov! Bu aklımı başımdan aldı! Kesinlikle öğreneceğim çok şey var.
maple_shaft

5

Clojure, 111 bayt

(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)))

Mümkün olan tüm pozisyonlarda böler ve ilk kısım bir palindrom olduğunda, ipin kalanı için bir bölümleme bulmaya devam eder.

Çevrimiçi deneyin .

Ungolfed, iş parçacığı-son makro kullanır ->>.

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

Belirsiz bir sürüm, lütfen böyle bir kod yazmayın: 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)))

Misiniz bu uç yardım? Clojure'u hiç tanımıyorum.
Leaky Nun

Genelde evet, fakat bu durumda işlev fkendini for: içinde çağırmak zorundadır (f b). Kuyruk arama konumunda kullanabilirsiniz recur.
NikoNyrh

Hala yerini alabilir defnile fnve sadece bir işlevi vardır.
cliffroot

(fn f[s]( ... ))? Ah doğru. Bununla 2 karakter kaydedersiniz.
NikoNyrh

5

JavaScript (ES6), 143 126 124 bayt

Neil sayesinde 2 bayt kaydedildi

NikoNyrh yönteminden esinlenilmiştir .

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)

Biçimlendi ve yorumlandı

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()

Test durumları


İlk yaklaşım 173 168 bayt

Giriş dizesinin tüm olası bölümlerini hesaplayan oldukça uzun özyinelemeli bir işlev.

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)

Biçimlendi ve yorumlandı

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

Test durumları


Açıklamanızı doğru anladıysam ,p=0, s[p++]?ve tuşlarını kullanarak birkaç bayt kaydedebilirsiniz ,F(s,i,p).
Neil

@Neil Evet gerçekten. :-)
Arnauld

5

Jöle , 10 bayt

ŒṖŒḂ€¬$ÞḢL

Çevrimiçi deneyin!

Nasıl?

Şunu kullanır
[0]<[0,0]<[0,0,0],...,<[0,...,0,1]<...
- yani eğer bölümleri "her bölüm için palindromik değildir" anahtarına göre sıralarsak, ilk girişin tümü palindromik ve minimum uzunlukta olacaktır.

Not: Boş olmayan uzunluktaki n dizeleri her zaman n sıfırlı bir tuşa neden olur , çünkü tüm uzunluk 1 dizeleri palindromiktir.

ŒṖŒḂ€¬$ÞḢ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

Haskell , 69 bayt

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

Bir fonksiyon tanımlar f. Çevrimiçi deneyin!

açıklama

Sabitleme yardımcı işlevi x ! y, bozulmamış halde bırakılan reverse x ++ ypalindromlara bazı parçaların uzunluğu olan bir tamsayı listesi hesaplar reverse x. yBoş değilse , minimum bölmenin uzunluğunu içermesi garanti edilir . Nasıl çalışır?

  • yBoş değilse , bir karakter fırlatılıp atılır x. xBir palindrom olursa f, kuyruğundaki ana işlevi çağırır ve yhesaba katmayı 1 ekleriz x. Ayrıca, !yeni xvey potansiyel bölünmeyi kaçırmamaya çalışıyoruz.
  • Eğer yboştur, biz dönmek [0](0 uzunluğunda bir bölme) eğer xda boştur ve [](hiçbir ayrışması) aksi.

Ana işlev fsadece çağırır "" ! xve sonuçların minimumunu alır.

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 bayt

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 bağlantı noktası:

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>

Bir şey unuttuğumu sandığım kadar basit bir çözüm gibi görünüyor ama en azından tüm sınav durumlarını geçiyor.


1

Haskell, 139 116 109 bayt

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 golf sahasında hala yeşil ama işte çabuk karşılaşabileceğim en iyi girişim bu.

  • h, bir Listenin tüm olası bitişik alt dizilerinin bir listesini oluşturan bir fonksiyondur (bir dize gibi). String girişini alır ve g için ayırır.
  • r, bir liste palindrome ise, Boole döndüren basit bir fonksiyondur.
  • g, bir Giriş Listesini alan ana işlevdir, bitişik olasılık olasılıklarının listesini almak için h'yi çağırır (and.map r), bir palindrom içermeyen alt listeleri çıkarmak için filtreler, listeye nokta uzunluğu uygulanır ve sonuç Sıraladığımız şey, cevap olan başı alabilmemiz.

Başvuruların kullanımı yoluyla Haskell'deki Listelerin deterministik olmayan doğasından daha iyi bir cevap alabileceğimi düşünüyordum. Control.Applicative'i içe aktarmamız gerekse bile, uygulamaları kullanarak h işlevinin bir çok baytını tıraş etmek mümkün olabilir. İyileştirme için yorumlarınızı bekliyoruz.

UPDATE1

Asgari işlev hakkında Laikoni'nin hatırlatmasına dayanan muazzam tasarruf. Sıralamanın kaldırılması asıl olarak Prelude! 'Da tanımlandığından Data.List içe aktarmayı bırakmama izin verdi.

Update2

Nimi'nin liste kavramalarını filter.map için faydalı bir alternatif olarak kullanmaya ilişkin önerisi sayesinde. Bu beni birkaç bayt kurtardı. Ayrıca Laikonis'in cevabından düzgün bir String bölümü aldım ve birkaç bayt da orda sakladım.


1
h []=[[]]ve h (x:y)=map ([x]:)gereksiz beyaz boşluk içerir. head.sortolduğunu minimum.
Laikoni

@Likonik Teşekkürler! Bilgisayarıma geri döndüğümde güncelleme yapacağım!
maple_shaft

1
Bir liste anlama genellikle filter& map: dan daha kısadır g x=head$sort[length y|y<-h x,and$r<$>y].
nimi

@nimi Teşekkürler, Haskell için çok faydalı golf ipuçları var. Her zaman yeni bir numara öğrenirim.
maple_shaft

1

PHP, 319 Bayt

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;

Çevrimiçi sürüm

Expanded

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 olmadan daha uzun sürüm ve sonuç dizisinin çıktısını al


Bu,ababacabBACABABA
Zgarb

@Zgarb Şimdi çalışıyor
Jörg Hülsermann
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.