Palindromes ที่สมบูรณ์แบบ


25

งานของคุณคือการกำหนดจำนวนสายอักขระที่สมบูรณ์แบบของสตริง palindrome ทั่วไปของคุณ (เช่น 12321) เป็น palindrome ที่สมบูรณ์แบบ ความสมบูรณ์แบบคือ 1

ในการกำหนดความสมบูรณ์แบบของสตริงคุณจะเห็นว่าคุณสามารถแบ่งส่วนต่างๆออกเป็นส่วนต่างๆซึ่งแต่ละส่วนเป็น Palindrome หากมีความคลุมเครือเช่นด้วยaaaaในขณะที่คุณสามารถแยกมันออกเป็น[aa, aa]หรือ[aaaa]หรือ[a, aaa]หรือ[aaa, a]ชุดที่สั้นที่สุดจะแทนที่ให้aaaaคะแนน 1 ซึ่งเป็นความยาวของชุดที่สั้นที่สุด

ดังนั้นคุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่จะรับอินพุตและเอาต์พุตที่ไม่ว่างหนึ่งอันสมบูรณ์แบบ (ซึ่งเป็นความยาวของเซ็ตที่สั้นที่สุดที่คุณสามารถแยกมันออกเป็นส่วน ๆ ของแต่ละอิลิเมนต์ในชุด)

ตัวอย่าง:

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 เช่นเดียวกับข้อโต้แย้งที่ดีว่าเป็นไปได้ว่าขั้นตอนวิธีเชิงเส้นเป็นไปได้
Leun 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)

คุณเอาชนะฉัน ... ในโพสต์แรกของฉันฮ่า ๆ
Leaky Nun

7
@LeakyNun ฉันรู้ว่าคุณจะลอง เดือนที่แล้วฉันสามารถหย่อนและรอไม่กี่ชั่วโมงตอนนี้กับคุณกลับฉันต้องตอบทันที!
ลดขนาด

9

เยลลี่ , 13 12 11 ไบต์

ÞŒḂLÞŒḂ€ P $ 
ÐfḢLŒṖLÞṚ€⁼ $ ÐfḢL
ŒṖṚ€⁼ $ DFL € M
ŒṖรับพาร์ติชัน
      filterf filter สำหรับพาร์ติชั่นที่
  Ṛ€หลังจากย้อนกลับแต่ละส่วนย่อย
    ⁼เท่ากับพาร์ติชัน
        ความยาว L €ของแต่ละพาร์ติชันที่ประสบความสำเร็จ
          Ṃขั้นต่ำ

ลองออนไลน์!

รายละเอียด

  • อินพุต: "ababacab"(เป็นอาร์กิวเมนต์)
  • เอาท์พุท: 2

3
@Okx คุณจะต้องหลบหนีจากเหล่านั้น
Leun Nun

2
ฉันคิดว่ามันไม่ถูกต้องถ้ามันไม่สามารถรับแบ็กสแลชได้
Okx

14
@Okx มันเหมือนกับการเขียนสตริง คุณไม่สามารถคาดหวังได้ว่าโปรแกรม C จะทำงานกับอินพุตสตริงได้"\"เนื่องจากเป็นไวยากรณ์ที่ไม่ถูกต้อง
Conor O'Brien

2
ยินดีต้อนรับกลับมาโดยวิธี :-)
Arnauld

2
น่าเศร้าที่สิ่งนี้ให้คำตอบที่ต่างกันababacabและย้อนกลับbacababa.
Neil

6

Pyth, 9 ไบต์

lh_I#I#./

ชุดทดสอบ

สิ่งนี้สร้างพาร์ติชั่นของอินพุตทั้งหมดจากสั้นที่สุดถึงยาวที่สุด จากนั้นจะกรองพาร์ติชันเหล่านั้นบนค่าคงที่ภายใต้การกรององค์ประกอบบนค่าคงที่ภายใต้การกลับรายการ ในที่สุดเราใช้องค์ประกอบแรกของรายการพาร์ติชั่นที่กรองแล้วและคืนความยาว

_Iที่จะอธิบายว่าขั้นตอนที่ซับซ้อนขอเริ่มต้นด้วยความไม่แปรเปลี่ยนภายใต้การกลับรายการ: ที่ตรวจสอบว่าการป้อนข้อมูลของมันเป็น Palindrome หรือไม่เพราะมันจะตรวจสอบว่าการย้อนกลับมีการเปลี่ยนแปลงค่า

ถัดไปกรองความ_I#รุนแรง: สิ่งนี้จะเก็บเฉพาะองค์ประกอบ palindromic ของรายการ

ต่อไปเราจะตรวจสอบค่าความไม่แปรเปลี่ยนภายใต้การกรองสำหรับความ_I#Iรุนแรง: นี่คือความจริงถ้าหากองค์ประกอบทั้งหมดของรายการเป็น palindromes

สุดท้ายเรากรองสำหรับรายการที่ทุกองค์ประกอบของรายการที่มี _I#I#palindromes:


ฉันมีอะไรมากมายให้เรียนรู้ ...
Leun Nun

6

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

Clojure, 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)))

แยกที่ตำแหน่งที่เป็นไปได้ทั้งหมดและเมื่อส่วนแรกคือ palindrome ดำเนินการเพื่อค้นหาการแบ่งพาร์ติชันสำหรับส่วนที่เหลือของสตริง

ลองมันออนไลน์

Ungolfed ใช้แมโครกระทู้สุดท้าย ->>

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

เคล็ดลับนี้จะช่วยได้ไหม ฉันไม่รู้จัก Clojure เลย
Leun Nun

มักจะใช่ แต่ในกรณีนี้ฟังก์ชั่นที่มีการเรียกตัวเองภายในสำหรับ:f ในตำแหน่งหางโทรคุณสามารถใช้(f b)recur
NikoNyrh

คุณยังสามารถแทนที่defnด้วยfnและเพียงแค่มีฟังก์ชั่น
หน้าผา

(fn f[s]( ... ))? โอ้จริง คุณบันทึกได้ 2 ตัวอักษรด้วย
NikoNyrh

5

JavaScript (ES6), 143 126 124 ไบต์

บันทึก 2 ไบต์ต้องขอบคุณ Neil

แรงบันดาลใจจากวิธี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]<...
- ดังนั้นถ้าเราเรียงพาร์ทิชันด้วยคีย์ "ไม่ใช่ palindromic สำหรับแต่ละส่วน" รายการแรกจะเป็น palindromic ทั้งหมดและมีความยาวน้อยที่สุด

หมายเหตุ: การใด ๆ สตริงไม่ว่างเปล่าของความยาวnมักจะส่งผลในการดังกล่าวที่สำคัญที่มีnศูนย์เนื่องจากทุกความยาว1สตริง palindromic

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

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

fกำหนดฟังก์ชั่น ลองออนไลน์!

คำอธิบาย

ฟังก์ชั่น infix helper x ! yคำนวณรายชื่อจำนวนเต็มซึ่งเป็นความยาวของ splittings บางส่วนของreverse x ++ yเป็น palindromes ที่reverse xเหลืออยู่เหมือนเดิม มันรับประกันว่าจะมีความยาวของการแยกน้อยที่สุดหากyไม่ได้รับการยกเว้น มันทำงานอย่างไร

  • ถ้าyเป็นว่าง, xถ่านจะโผล่ออกมันและผลักดันให้เป็น หากxกลายเป็นประโยคที่เราเรียกใช้ฟังก์ชันหลักfบนหางของyและเพิ่ม 1 xถึงบัญชี นอกจากนี้เราขอเรียกร้อง!ให้ใหม่xและyไม่พลาดการแยก
  • ถ้า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

Haskell, 139 116 109 bytes

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 แต่นี่คือความพยายามที่ดีที่สุดของฉันที่ฉันสามารถทำได้อย่างรวดเร็ว

  • h คือฟังก์ชั่นที่สร้าง List ขององค์ประกอบที่ต่อเนื่องที่เป็นไปได้ทั้งหมดของ List (เช่นสตริง) มันจะใช้สตริงอินพุตและแบ่งออกเป็นกรัม
  • r เป็นฟังก์ชั่นง่าย ๆ ที่คืนค่าบูลีนถ้า List เป็นแพลง
  • g คือฟังก์ชั่นหลักที่รับรายการอินพุต, เรียก h เพื่อรับรายการความเป็นไปได้ของการเรียงลำดับที่เป็นไปได้, ตัวกรอง(and.map r)เพื่อลบรายการย่อยที่ไม่มี palindrome, ที่ความยาวจุดถูกนำไปใช้กับรายการแล้วผลลัพธ์คือ เรียงลำดับเพื่อให้เราสามารถคว้าหัวซึ่งเป็นคำตอบ

ฉันคิดว่าคำตอบที่ดีกว่าอาจสามารถใช้ประโยชน์จากรายการที่ไม่ได้กำหนดไว้ใน Haskell ผ่านทางการใช้งานของแอปพลิเคชัน อาจเป็นไปได้ที่จะโกนหลายไบต์ออกจากฟังก์ชัน h โดยใช้แอปพลิเคชันแม้ว่าเราจะต้องนำเข้า Control.Applicative ความคิดเห็นสำหรับการปรับปรุงยินดีต้อนรับ

UPDATE1

ประหยัดมากจากการเตือนของ Laikoni เกี่ยวกับฟังก์ชั่นขั้นต่ำ การลบการเรียงลำดับทำให้ฉันสามารถนำเข้า Data.List ได้เนื่องจากการกำหนดขั้นต่ำใน Prelude!

UPDATE2

ขอขอบคุณข้อเสนอแนะของ nimi เกี่ยวกับการใช้รายการความเข้าใจแทนการแทนที่ filter.map ที่มีประโยชน์ นั่นช่วยฉันสองสามไบต์ นอกจากนี้ฉันยังยืมเคล็ดลับการแบ่งสตริงที่เรียบร้อยจาก 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örgHülsermann
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.