ปัญหาการแตกสร้อยคอ


19

พื้นหลัง

ผมได้รับแรงบันดาลใจจาก3Blue1Brown 's ล่าสุดวิดีโอเกี่ยวกับปัญหาสร้อยคอแยก (หรือในขณะที่เขาเรียกมันว่าเป็นปัญหาที่ถูกขโมยสร้อยคอ) และความสัมพันธ์กับทฤษฎีบท Borsuk-ลาม

ในปัญหานี้โจรสองคนได้ขโมยสร้อยคอที่มีค่าซึ่งประกอบด้วยอัญมณีหลายประเภท อัญมณีแต่ละชนิดมีจำนวนเท่ากันและพวกโจรต้องการที่จะแยกอัญมณีแต่ละชนิดให้เท่ากันในหมู่พวกเขาสองคน จับเป็นที่พวกเขาจะต้องทำเช่นนั้นโดยการแยกสร้อยเป็นส่วนที่ต่อเนื่องกันจำนวนหนึ่งและกระจายส่วนระหว่างสองของพวกเขา

นี่คือตัวอย่างที่มีสี่ประเภทอัญมณีแสดงS, E, DและR(สำหรับไพลินมรกตเพชรและทับทิมตามลำดับ) สมมติว่าสร้อยคอมีดังนี้:

[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]

มี8ไพลิน, 10มรกต, 4เพชรและ6ทับทิม เราสามารถแยกสร้อยคอดังนี้:

[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]

จากนั้นถ้าเราให้ส่วนที่หนึ่ง, สามและห้าแก่ขโมยหนึ่งและส่วนที่สองและสี่กับขโมยอื่น ๆ แต่ละอันจะจบลงด้วย4ไพลิน, 5มรกต, 2เพชรและ3ทับทิม:

[S],    [S,E,S,D,E,R,S],                            [R,R,D,E,E,E]
    [S],                [R,E,S,S,S,D,R,E,E,R,E,D,E],

ใช้0-indexing [1,2,9,22]ตัดเหล่านี้เกิดขึ้นในดัชนี

เป้าหมาย

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

อินพุต

อินพุตอาจอยู่ในรูปแบบที่สะดวก สร้อยคอควรเป็นลำดับของอัญมณีและไม่มีอะไรเพิ่มเติม เช่นรายการจำนวนเต็มพจนานุกรมที่มีกุญแจซึ่งเป็นตัวแทนประเภทอัญมณีและค่าเป็นรายการดัชนี คุณอาจเลือกที่จะรวมความยาวของสร้อยคอหรือจำนวนอัญมณีที่แตกต่างกัน แต่คุณไม่ควรใช้อินพุตอื่น

คุณอาจคิดว่าสร้อยคออินพุตนั้นถูกต้อง คุณไม่จำเป็นต้องจัดการกับกรณีที่มีอัญมณีแปลก ๆ จำนวนหนึ่งหรือสร้อยคอนั้นว่างเปล่า

เอาท์พุต

อีกครั้งเอาต์พุตอาจอยู่ในรูปแบบที่สะดวก เช่นรายการของเซ็กเมนต์, รายการของตำแหน่งที่ตัด, พจนานุกรมที่มีกุญแจซึ่งเป็นตัวแทนของขโมยสองคนและค่านิยมที่เป็นรายการของเซกเมนต์ ฯลฯ ส่วนต่างๆอาจแสดงโดยดัชนีเริ่มต้นของพวกเขา, ดัชนีสิ้นสุด, รายการดัชนีต่อเนื่อง, รายการอัญมณี ความยาวของพวกเขา ฯลฯ คุณสามารถใช้0- หรือ1- การจัดทำดัชนี หากการสั่งซื้อไม่สำคัญกับรูปแบบของคุณผลลัพธ์ของคุณอาจอยู่ในลำดับใดก็ได้ นี่คือผลลัพธ์ข้างต้นในหลายรูปแบบ:

list of segments: [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
list of cuts:     [1,2,9,22]
list of lengths:  [1,1,7,13,6]
dictionary:       {'thief1' : [(R,R,D,E,E,E),(S),(S,E,S,D,E,R,S)], 'thief2' : [(S),(R,E,S,S,S,D,R,E,E,R,E,D,E)]}

โปรดทราบว่าคำสั่งนั้นสำคัญในรายการของเซกเมนต์ (เซกเมนต์สำรองระหว่างขโมย) และรายการของความยาว (เพื่อระบุเซกเมนต์) แต่ไม่ได้อยู่ในรายการของการตัดหรือพจนานุกรม แก้ไข: Greg Martin ชี้ให้เห็นว่าสิ่งเหล่านี้จะไม่เป็นผลลัพธ์ที่ถูกต้องเนื่องจากสามารถแบ่งแผนกออกเป็นสองส่วนได้

กรณีทดสอบ

[1,2,1,2,1,3,1,3,3,2,2,3] -> [[1,2,1],[2,1,3,1],[3,3,2],[2,3]]
[1,1,1,1,2,2,3,3,3,3,3,3] -> [[1,1],[1,1,2],[2,3,3,3],[3,3,3]]
[1,1,1,1,1,1,1,1,1,1,1,1] -> [[1,1,1,1,1,1],[1,1,1,1,1,1]]
[1,1,1,1,2,3,4,2,3,4,2,2] -> [[1,1],[1,1,2,3,4,2],[3,4,2,2]]

หมายเหตุ

  1. ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม
  2. นี่คือ ; คำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

2
สร้อยคอเป็นวงกลมหรือไม่?
เดนนิส

1
@Dennis No สร้อยคอเป็นเส้นตรง
ngenisis

1
เราสามารถรับอินพุตเป็นตัวอักษร / โทเค็นเพื่อระบุประเภทอัญมณีที่แตกต่างกันแทนที่จะเป็นจำนวนเต็มได้หรือไม่
เกร็กมาร์ติน

3
หากไม่มีการเปลี่ยนแปลงลำดับของเซ็กเมนต์ชิ้นส่วนที่สลับกันระหว่าง theif A และ theif B เช่นนี้รวมถึงข้อมูลในเอาต์พุตนั้นซ้ำซ้อน เราสามารถละเว้นการบ่งชี้ของพวกเขาได้หรือไม่ถ้าคำตอบไม่เปลี่ยนลำดับของอัญมณี? คุณมีกรณีทดสอบบ้างไหม?
ลุค

2
สำหรับตัวอย่างของคุณ[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]มันก็ดูเหมือนว่าการส่งออกควรจะนับตั้งแต่ที่มีการปรับลดน้อยกว่า[[S,S,S,E,S,D,E,R],[S,R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]] [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]ฉันเข้าใจสเป็คอย่างถูกต้องหรือไม่?
Greg Martin

คำตอบ:


3

Brachylogขนาด 13 ไบต์

~c.ġ₂z₁Ċcᵐoᵛ∧

ลองออนไลน์!

หมายเหตุ: การเปรียบเทียบนั้นใหม่กว่าความท้าทายนี้

คำอธิบาย

~c.ġ₂z₁Ċcᵐoᵛ∧  Input is a list, say L = [1,2,2,2,1,2,3,3]
~c.            Output is a partition of the input: [[1,2,2],[2,1,2],[3],[3]]
  .ġ₂          Split the output into chunks of length 2: [[[1,2,2],[2,1,2]],[[3],[3]]]
     z₁        Zip (transpose) the chunks: [[[1,2,2],[3]],[[2,1,2],[3]]]
       Ċ       This is a 2-element list (forbid the trivial partition).
        cᵐ     Concatenate both: [[1,2,2,3],[2,1,2,3]]
          oᵛ   If you sort both lists, they are equal.
            ∧  Don't unify with the output.

พาร์ติชันถูกระบุตามลำดับการเพิ่มจำนวนของบล็อกดังนั้นผลลัพธ์จะมีบล็อกน้อยที่สุด


3

เยลลี่ขนาด 18 ไบต์

s2ZFṢ$€E¬,L
ŒṖṖÇÞḢ

ลองออนไลน์!

ไม่มีประสิทธิภาพ - ตัวอย่างมี28รัตนากรที่ไม่ทำงานโดยไม่มีทรัพยากรขนาดใหญ่เนื่องจากขั้นตอนแรกของการนำไปใช้จะต้องสร้างรายการของพาร์ติชันที่เป็นไปได้2 27

ส่งคืนรายการของรายการ - ส่วนต่าง ๆ เพื่อล้างออกระหว่างขโมยอื่น (Re เอาท์พุท TIO: เมื่อรายการมีเพียงรายการเดียวการพิมพ์โดยนัยจะไม่รบกวนกับวงเล็บ[])

อย่างไร?

s2ZFṢ$€E¬,L - Link 1, get (isUnfair, Slices): A possible partition
s2          - split into slices of length 2 (any odd one on it's own at the end)
  Z         - transpose (first item is one thief's slices, second is the others)
     $€     - last two links as a monad for €ach
   F        -     flatten
    Ṣ       -     sort
       E    - equal? (theif1's jewels == theif2's jewels)
        ¬   - not
          L - length (number of slices in the partition)
         ,  - pair

ŒṖṖÇÞḢ - Main link: necklace
ŒṖ     - all partitions
  Ṗ    - pop, we must remove the rightmost one...
              because Link 1 will say it is fair, and it will have length 1!
              (a list of one thing has all entries equal)
    Þ  - sort by
   Ç   -     last link (1) as a monad
     Ḣ - head (get the first one, i.e. minimal isUnfair, then minimal length)

3

Mathematica, 118 ไบต์

เกือบจะชนะ Jelly ... เพียง 1 off;)

SelectFirst[l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};i=#;(i±#)&/@Range@#2~Subsets~#3,Tr[Tr/@#]==0&]&

ฟังก์ชั่นบริสุทธิ์รับสามข้อโต้แย้ง: สร้อยคอเป็นรายการของสัญญาณเช่น{A, A, A, A, B, C, D, B, C, D, B, B}; ความยาวของสร้อยคอ; และจำนวนเวลาอัญมณีที่แตกต่างกัน มันส่งกลับรายการของรายการย่อยในรูปแบบ{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}ที่โทเค็นที่ไม่มีสัญญาณเชิงลบไปที่หนึ่งขโมยและโทเค็นที่มีสัญญาณเชิงลบไปที่ขโมยอื่น (ในขณะที่นี่คือข้อมูลที่ซ้ำซ้อนอัลกอริทึมจะนำไปสู่การเป็นตัวแทนนี้และการลบเครื่องหมายลบจะมีค่าใช้จ่ายหลายไบต์)

ก่อนอื่นเราต้องใช้ฟังก์ชั่นที่รับ list และเซตของncut-places และส่งคืน list ของn+1sublist ที่ได้รับโดยการตัด list ที่ input n-cut เหล่านั้น; ผู้ประกอบการมัดไบนารีถูกนำมาใช้เพื่อการนี้และกำหนดซ้ำผ่าน± l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};เนื่องจากเครื่องหมายลบติดลบAppendผลลัพธ์ก็คือรายการย่อยจะสลับกันและไม่มีสัญญาณลบติดอยู่กับแต่ละโทเค็น

จากนั้นเราสร้างชุดตัดที่เป็นไปได้ทั้งหมดซึ่งมีความยาวไม่เกินจำนวนประเภทอัญมณีการใช้Range@#2~Subsets~#3และใช้i=#;(i±#)&/@เพื่อใช้±โอเปอเรเตอร์ (พร้อมรายการอินพุตของอัญมณี) กับชุดตัดแต่ละชุด

ในที่สุดSelectFirst[...,Tr[Tr/@#]==0&]&เลือกหน่วยสร้อยคอที่เกิดขึ้นเป็นครั้งแรกที่ยุติธรรม มันทำได้โดยการเพิ่มองค์ประกอบทั้งหมดในรายการย่อยทั้งหมด Mathematica นั้นฉลาดพอที่จะยกเลิกการคัดลอกโทเค็นทั้งบวกและลบในวิธีที่ชัดเจน


3

Pyth, 16 ไบต์

hfqFSMsM.TcT2t./

ลองใช้ออนไลน์: การสาธิตหรือชุดทดสอบ

คำอธิบาย:

hfqFSMsM.TcT2t./Q   implicit Q (=input) at the end
              ./Q   create all partitions of the input list 
                    (they are already sorted by number of cuts)
             t      remove the partition with zero splits
 f                  filter for partitions T, which satisfy:
          cT2          chop into pieces of length 2
        .T             transpose to get the pieces of each thieve
    SMsM               combine all pieces for each thieve and sort the results
  qF                   check if they got the same jewels
h                   print the first such partition

1

05AB1E , 14 ไบต์

.œ¨ʒ2ôζε˜{}Ë}¤

ลองมันออนไลน์หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย:

                # All partitions of the (implicit) input
                  #  i.e. [2,3,2,1,3,1]
                  #   → [[[2],[3],[2],[1],[3],[1]],[[2],[3],[2],[1],[3,1]],
                  #      ...,[[2,3,2,1,3,1]]]
  ¨               # Remove the last one
   ʒ        }     # Filter this list by:
    2ô            # Split it into parts of 2
                  #  i.e. [[2,3],[2],[1],[3,1]] → [[[2,3],[2]],[[1],[3,1]]]
                  #  i.e. [[2,3,2],[1,3],[1]] → [[[2,3,2],[1,3]],[[1]]]
      ζ           # Swap rows and columns (using space as filler if necessary)
                  #  i.e. [[[2,3],[2]],[[1],[3,1]]] → [[[2,3],[1]],[[2],[3,1]]]
                  #  i.e. [[[2,3,2],[1,3]],[[1]]] → [[[2,3,2],[1]],[[1,3]," "]]
       ε  }       # Map each inner list to:
        ˜         # Flatten the list
                  #  i.e. [[2,3],[1]] → [2,3,1]
                  #  i.e. [[1,3]," "] → [1,3," "]
         {        # Sort the list
                  #  i.e. [2,3,1] → [1,2,3]
                  #  i.e. [1,3," "] → [1,3," "]
           Ë      # Check if both sorted lists are equal
                  # (if not, remove them from the partitions)
             ¤    # After filtering, take the last one as result (and output implicitly)
                  #  i.e. [[[2],[3,2],[1,3],[1]],[[2,3],[2],[1],[3,1]]]
                  #   → [[2,3],[2],[1],[3,1]]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.