Masalah membelah kalung

19

Latar Belakang

Saya terinspirasi oleh 3Blue1Brown 's baru-baru ini video yang tentang masalah kalung membelah (atau saat ia menyebutnya, masalah kalung itu dicuri) dan hubungannya dengan teorema Borsuk-Ulam .

Dalam masalah ini, dua pencuri telah mencuri kalung berharga yang terdiri dari beberapa jenis permata. Ada bahkan jumlah setiap jenis permata dan pencuri ingin membagi setiap jenis permata secara merata di antara keduanya. Tangkapannya adalah bahwa mereka harus melakukannya dengan membelah kalung itu menjadi beberapa segmen yang berdekatan dan mendistribusikan segmen tersebut di antara mereka berdua.

Berikut adalah contoh dengan empat jenis permata dilambangkan S, E, D, dan R(untuk safir, zamrud, berlian, dan ruby, masing-masing). Katakanlah kalung itu adalah sebagai berikut:

[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]

Ada 8safir, 10zamrud, 4berlian, dan 6rubi. Kita dapat membagi kalung itu sebagai berikut:

[[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]]

Kemudian jika kita memberikan segmen pertama, ketiga, dan kelima untuk satu pencuri dan segmen kedua dan keempat untuk pencuri yang lain, masing-masing akan berakhir dengan 4safir, 5zamrud, 2berlian, dan 3rubi:

[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],

Menggunakan 0-indexing, pemotongan ini terjadi pada indeks [1,2,9,22].

Tujuan

Ternyata pembagian yang adil seperti itu selalu bisa dilakukan menggunakan paling banyak npemotongan, di mana njumlah jenis permata. Tugas Anda adalah untuk menulis program atau fungsi lengkap yang mengambil kalung sebagai input dan menghasilkan divisi minimal seperti itu (jumlah pemotongan paling sedikit).

Memasukkan

Input mungkin dalam format apa pun yang nyaman. Kalung itu harus menjadi urutan permata dan tidak lebih dari itu; misalnya daftar bilangan bulat, kamus dengan kunci yang mewakili jenis permata dan nilai yang menjadi daftar indeks. Anda bisa memasukkan panjang kalung atau jumlah jenis permata yang berbeda, tetapi Anda tidak boleh mengambil input lain.

Anda dapat mengasumsikan bahwa kalung input valid. Anda tidak perlu menangani kasing di mana ada jumlah permata yang ganjil dari jenis yang diberikan atau kalung itu kosong.

Keluaran

Sekali lagi, output mungkin dalam format yang mudah; misalnya daftar segmen, daftar posisi pemotongan, kamus dengan kunci yang mewakili dua pencuri dan nilai menjadi daftar segmen, dll. Segmen dapat diwakili oleh indeks awal, indeks akhir, daftar indeks berturut-turut, daftar perhiasan, panjangnya, dll. Anda dapat menggunakan 0- atau 1- pengindeksan. Jika pemesanan tidak signifikan untuk format Anda, maka output Anda mungkin dalam urutan apa pun. Berikut ini adalah output di atas dalam beberapa format berbeda:

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)]}

Perhatikan bahwa urutan penting dalam daftar segmen (segmen bergantian antara pencuri) dan daftar panjang (untuk mengidentifikasi segmen), tetapi tidak dalam daftar potongan atau kamus. Sunting: Greg Martin menunjukkan bahwa ini tidak akan menjadi hasil yang valid karena pembagian yang adil dapat diperoleh dalam dua pemotongan

Uji kasus

[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]]

Catatan

  1. Celah standar dilarang.
  2. Ini adalah ; jawaban terpendek (dalam byte) menang.
ngenisis
sumber
2
Apakah kalung itu bundar?
Dennis
1
@ Dennis Tidak, kalung itu linear.
ngenisis
1
Bisakah kita mengambil input sebagai huruf / token yang menunjukkan berbagai jenis permata, bukan bilangan bulat?
Greg Martin
3
Jika urutan segmen tidak berubah, potongan berganti-ganti antara theif A dan theif B. Dengan demikian, termasuk bahwa informasi dalam output berlebihan. Bisakah kita menghilangkan indikasi jika jika jawabannya tidak mengubah urutan perhiasan? Anda punya beberapa test case?
Luke
2
Misalnya Anda [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], tampaknya output harus [[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]], karena yang memiliki luka kurang dari [[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]]. Apakah saya memahami spesifikasi dengan benar?
Greg Martin

Jawaban:

3

Brachylog , 13 byte

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

Cobalah online!

Catatan: metapredicate lebih baru dari tantangan ini.

Penjelasan

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

Partisi disebutkan dalam urutan jumlah blok yang meningkat, sehingga hasilnya akan memiliki blok sesedikit mungkin.

Zgarb
sumber
3

Jelly , 18 byte

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

Cobalah online!

Tidak efisien - contoh memiliki 28 jewels yang bekerja wont tanpa sumber daya yang besar sejak langkah pertama pelaksanaan ini akan membangun daftar 2 27 partisi mungkin.

Mengembalikan daftar daftar - segmen dalam urutan untuk mengeluarkannya di antara pencuri alternatif. (Re output TIO: ketika daftar hanya memiliki satu item, cetakan implisit tidak mengganggu kurung, [])

Bagaimana?

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)
Jonathan Allan
sumber
3

Mathematica, 118 byte

Hampir mengalahkan Jelly ... hanya 1 off;)

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

Fungsi murni mengambil tiga argumen: kalung, sebagai daftar token seperti {A, A, A, A, B, C, D, B, C, D, B, B}; panjang kalung; dan jumlah waktu permata yang berbeda. Ini mengembalikan daftar sublists dalam bentuk {{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}, di mana token tanpa tanda negatif pergi ke satu pencuri dan token dengan tanda negatif pergi ke pencuri yang lain. (Walaupun ini adalah informasi yang berlebihan, algoritma mengarah ke representasi ini, dan menghilangkan tanda-tanda negatif akan menelan biaya beberapa byte.)

Pertama-tama kita harus mengimplementasikan fungsi yang mengambil daftar dan sekumpulan ntempat-potong dan mengembalikan daftar n+1sub -daftar yang diperoleh dengan memotong daftar input di ntempat-tempat tersebut; operator infiks biner ±digunakan untuk tujuan ini, dan didefinisikan secara rekursif melalui l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};. Karena tanda negatif tepat setelahnya Append, hasilnya adalah bahwa sublisensi secara bergantian melakukan dan tidak memiliki tanda-tanda negatif yang melekat pada setiap token.

Kemudian kami membuat semua set tempat cut yang panjangnya paling banyak jumlah jenis permata, menggunakan Range@#2~Subsets~#3, dan menggunakan i=#;(i±#)&/@untuk menerapkan ±operator (dengan daftar input perhiasan) untuk masing-masing set tempat cut ini pada gilirannya.

Akhirnya, SelectFirst[...,Tr[Tr/@#]==0&]&pilih yang pertama dari pembagian kalung yang adil. Ia melakukannya dengan menambahkan semua elemen dalam semua sublists; Mathematica cukup bijaksana untuk membatalkan salinan positif dan negatif dari setiap token dengan cara yang jelas.

Greg Martin
sumber
3

Pyth, 16 byte

hfqFSMsM.TcT2t./

Cobalah online: Demonstrasi atau Test Suite

Penjelasan:

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
Jakube
sumber
1

05AB1E , 14 byte

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

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

                # 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]]
Kevin Cruijssen
sumber