Проблема розщеплення намиста


19

Фон

Я був натхненний 3Blue1Brown «Недавнє відео про проблему розщеплення намиста (або, як він його називає, проблему вкраденого намиста) та його зв’язок із теоремою Борсук-Улам .

У цій проблемі двоє злодіїв викрали коштовне намисто, що складається з декількох різних видів коштовностей. Існує парне число кожного виду коштовностей, і злодії хочуть рівномірно розділити кожен тип коштовності між ними. Проблема полягає в тому, що вони повинні зробити це, розділивши намисто на деяку кількість суміжних сегментів і розподіливши сегменти між ними.

Ось приклад із чотирма типами перлин 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)]}

Зауважте, що порядок важливий у списку сегментів (сегменти чергуються між злодіями) та списку довжин (з метою ідентифікації сегментів), але не у списку скорочень чи словника. Редагувати: Грег Мартін зазначив, що це не будуть дійсними результатами, оскільки справедливий поділ можна отримати в два скорочення

Тестові справи

[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 Ні, намисто лінійне.
ngenisis

1
Чи можемо ми взяти введення як букви / лексеми із зазначенням різних типів коштовності замість цілих чисел?
Грег Мартін

3
Якщо порядок сегментів не змінено, фрагменти чергуються між A і Thef 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]]. Я правильно розумію специфікацію?
Грег Мартін

Відповіді:


3

Брахілог , 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 можливих розділів.

Повертає список списків - сегментів для того, щоб розбити їх між черговими злодіями. (Повторіть вихід 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

Математика, 118 байт

Майже бити желе ... всього 1 раз;)

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}}, де жетони без негативних знаків переходять до одного злодія, а жетони з негативними знаками переходять до іншого злодія. (Хоча ця інформація є зайвою, алгоритм призводить до цього подання, а видалення негативних знаків коштуватиме кілька байтів.)

По-перше, ми повинні реалізувати функцію, яка займає список і набір nрозрізів і повертає список n+1підсписів, отриманий шляхом вирізання вхідного списку в цих nмісцях розрізів; ±для цього використовується оператор бінарної інфіксації і визначається рекурсивно через 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]]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.