Contexte
J'ai été inspiré par la récente vidéo de 3Blue1Brown sur le problème de division du collier (ou comme il l'appelle, le problème du collier volé) et sa relation avec le théorème de Borsuk-Ulam .
Dans ce problème, deux voleurs ont volé un précieux collier composé de plusieurs types de bijoux. Il existe un nombre pair de chaque type de bijou et les voleurs souhaitent répartir chaque type de bijou de manière égale entre les deux. Le hic, c'est qu'ils doivent le faire en divisant le collier en un certain nombre de segments contigus et en répartissant les segments entre les deux.
Voici un exemple avec quatre types de bijoux dénotés S
, E
, D
et R
(pour le saphir, émeraude, diamant et rubis, respectivement). Disons que le collier est le suivant:
[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]
Il y a des 8
saphirs, des 10
émeraudes, des 4
diamants et des 6
rubis. Nous pouvons diviser le collier comme suit:
[[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]]
Ensuite, si nous donnons les premier, troisième et cinquième segments à un voleur et les deuxième et quatrième segments à l'autre voleur, chacun se retrouvera avec des 4
saphirs, des 5
émeraudes, des 2
diamants et des 3
rubis:
[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],
En utilisant l' 0
indexation, ces coupes se produisent aux indices [1,2,9,22]
.
Objectif
Il s'avère qu'une telle division équitable peut toujours être effectuée en utilisant au plus des n
coupes, où n
est le nombre de types de bijoux. Votre tâche consiste à écrire un programme ou une fonction complète qui prend un collier en entrée et génère une telle division minimale (le moins de coupes).
Contribution
L'entrée peut être dans n'importe quel format pratique. Le collier doit être une séquence de bijoux et rien de plus; par exemple une liste d'entiers, un dictionnaire avec des clés représentant les types de bijoux et les valeurs étant des listes d'indices. Vous pouvez éventuellement inclure la longueur du collier ou le nombre de types de bijoux distincts, mais vous ne devez pas prendre d'autre entrée.
Vous pouvez supposer que le collier d'entrée est valide. Vous n'avez pas besoin de gérer le cas où il y a un nombre impair de bijoux d'un type donné ou le collier est vide.
Production
Encore une fois, la sortie peut être dans n'importe quel format pratique; par exemple une liste de segments, une liste de positions de coupe, un dictionnaire avec des clés représentant les deux voleurs et des valeurs étant des listes de segments, etc. Les segments peuvent être représentés par leur index de départ, index de fin, liste d'index consécutifs, liste de bijoux, leurs longueurs, etc. Vous pouvez utiliser 0
- ou 1
- l'indexation. Si la commande n'est pas importante pour votre format, votre sortie peut être dans n'importe quel ordre. Voici la sortie ci-dessus dans plusieurs formats différents:
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)]}
Notez que l'ordre est important dans la liste des segments (les segments alternent entre les voleurs) et la liste des longueurs (afin d'identifier les segments), mais pas dans la liste des coupes ou le dictionnaire. Edit: Greg Martin a souligné que ce ne seraient pas des sorties valides car une division équitable peut être obtenue en deux coupes
Cas de test
[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]]
Remarques
- Les failles standard sont interdites.
- C'est du golf de code ; la réponse la plus courte (en octets) l'emporte.
la source
[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]
, il semble que la sortie devrait être[[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]]
, car cela a moins de coupures que[[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]]
. Suis-je bien comprendre la spécification?Réponses:
Brachylog , 13 octets
Essayez-le en ligne!
Remarque: le métaprédicat
ᵛ
est plus récent que ce défi.Explication
Les partitions sont énumérées dans l'ordre croissant du nombre de blocs, donc le résultat aura le moins de blocs possible.
la source
Gelée , 18 octets
Essayez-le en ligne!
Pas efficace - l'exemple a 28 joyaux qui ne fonctionneront pas sans ressources énormes car la première étape de cette implémentation serait de construire une liste des 2 27 partitions possibles.
Renvoie une liste de listes - les segments dans l'ordre de les répartir entre des voleurs alternatifs. (Concernant la sortie TIO: lorsqu'une liste n'a qu'un seul élément, l'impression implicite ne dérange pas avec les crochets,
[]
)Comment?
la source
Mathematica, 118 octets
Presque battre Jelly ... juste 1 off;)
Fonction pure prenant trois arguments: le collier, comme une liste de jetons tels que
{A, A, A, A, B, C, D, B, C, D, B, B}
; la longueur du collier; et le nombre de fois distinctes. Il renvoie une liste de sous-listes sous la forme{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}
, où les jetons sans signe négatif vont à un voleur et les jetons avec signe négatif vont à l'autre voleur. (Bien qu'il s'agisse d'informations redondantes, l'algorithme conduit à cette représentation, et la suppression des signes négatifs coûterait plusieurs octets.)Nous devons d'abord implémenter une fonction qui prend une liste et un ensemble de
n
découpes et renvoie la liste desn+1
sous - listes obtenues en coupant la liste d'entrée à cesn
découpes; l'opérateur d'infixe binaire±
est utilisé à cet effet et défini de manière récursive parl_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};
. En raison du signe négatif juste aprèsAppend
, le résultat est que les sous-listes alternativement ont et n'ont pas de signes négatifs attachés à chaque jeton.Ensuite, nous générons tous les ensembles de coupes possibles dont la longueur est au plus le nombre de types de bijoux, en utilisant
Range@#2~Subsets~#3
et en utilisanti=#;(i±#)&/@
pour appliquer l'±
opérateur (avec la liste d'entrée des bijoux) à chacun de ces ensembles de coupes à tour de rôle.Enfin,
SelectFirst[...,Tr[Tr/@#]==0&]&
choisit la première des divisions de collier résultantes qui est juste. Il le fait en additionnant littéralement tous les éléments dans toutes les sous-listes; Mathematica est assez sage pour annuler les copies positives et négatives de chaque jeton de manière évidente.la source
Pyth, 16 octets
Essayez-le en ligne: démonstration ou suite de tests
Explication:
la source
05AB1E , 14 octets
Essayez-le en ligne ou vérifiez tous les cas de test .
Explication:
la source