Hintergrund
Ich war inspiriert von 3Blue1Brown ‚s jüngsten Video über die Halskette Spaltung Problem (oder , wie er es nennt, das gestohlene Halskette Problem) und seine Beziehung zum Borsuk-Ulam .
In diesem Problem haben zwei Diebe eine wertvolle Halskette gestohlen, die aus verschiedenen Arten von Juwelen besteht. Es gibt eine gerade Anzahl von Juwelen jeder Art, und die Diebe möchten jede Juwelenart gleichmäßig auf die beiden aufteilen. Der Haken ist, dass sie dies tun müssen, indem sie die Kette in eine Anzahl zusammenhängender Segmente aufteilen und die Segmente auf die beiden verteilen.
Hier ist ein Beispiel mit vier jewel Typen bezeichnet S
, E
, D
, und R
(für Saphir, Smaragd, Diamanten und Rubin, jeweils). Angenommen, die Halskette sieht wie folgt aus:
[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]
Es gibt 8
Saphire, 10
Smaragde, 4
Diamanten und 6
Rubine. Wir können die Kette wie folgt aufteilen:
[[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]]
Wenn wir dann das erste, dritte und fünfte Segment einem Dieb und das zweite und vierte Segment dem anderen Dieb geben, wird jedes mit 4
Saphiren, 5
Smaragden, 2
Diamanten und 3
Rubinen enden :
[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],
Mit 0
-indexing werden diese Schnitte an den Indizes ausgeführt [1,2,9,22]
.
Tor
Es stellt sich heraus, dass eine solche faire Aufteilung immer mit höchstens n
Schnitten durchgeführt werden kann, wobei n
die Anzahl der Edelsteintypen angegeben ist. Ihre Aufgabe ist es, ein komplettes Programm oder eine komplette Funktion zu schreiben, die eine Kette als Eingabe verwendet und eine minimale Teilung (die geringste Anzahl von Schnitten) ausgibt.
Eingang
Die Eingabe kann in einem beliebigen Format erfolgen. Die Kette sollte eine Abfolge von Juwelen sein und nichts weiter; zB eine Liste von ganzen Zahlen, ein Wörterbuch mit Schlüsseln, die die Edelsteintypen und -werte darstellen, wobei es sich um Listen von Indizes handelt. Sie können optional die Länge der Halskette oder die Anzahl der verschiedenen Edelsteintypen angeben, sollten jedoch keine weiteren Eingaben vornehmen.
Sie können davon ausgehen, dass die Eingabehalskette gültig ist. Sie müssen nicht mit dem Fall umgehen, in dem eine ungerade Anzahl von Juwelen eines bestimmten Typs vorhanden ist oder die Halskette leer ist.
Ausgabe
Auch hier kann die Ausgabe in jedem geeigneten Format erfolgen. zB eine Liste von Segmenten, eine Liste von Schnittpositionen, ein Wörterbuch mit Schlüsseln, die die beiden Diebe darstellen, und Werte, die Listen von Segmenten sind usw. Segmente können durch ihren Startindex, Endindex, Liste von aufeinanderfolgenden Indizes, Liste von Juwelen, ihre Länge usw. Sie können 0
- oder 1
- indizieren. Wenn die Reihenfolge für Ihr Format nicht von Bedeutung ist, kann die Ausgabe in beliebiger Reihenfolge erfolgen. Hier ist die obige Ausgabe in verschiedenen Formaten:
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)]}
Beachten Sie, dass die Reihenfolge in der Liste der Segmente (Segmente wechseln sich zwischen den Dieben ab) und der Liste der Längen (um die Segmente zu identifizieren) wichtig ist, nicht jedoch in der Liste der Schnitte oder im Wörterbuch. Edit: Greg Martin wies darauf hin, dass dies keine gültigen Ergebnisse sind, da eine faire Aufteilung in zwei Teile erzielt werden kann
Testfälle
[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]]
Anmerkungen
- Standardlücken sind verboten.
- Das ist Code-Golf ; kürzeste Antwort (in Bytes) gewinnt.
quelle
[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]
scheint es, dass die Ausgabe sein sollte[[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]]
, da das weniger Schnitte als hat[[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]]
. Verstehe ich die Spezifikation richtig?Antworten:
Brachylog , 13 Bytes
Probieren Sie es online!
Hinweis: Das Metapredikat
ᵛ
ist neuer als diese Herausforderung.Erläuterung
Die Partitionen werden in aufsteigender Reihenfolge der Anzahl der Blöcke aufgelistet, damit das Ergebnis so wenig Blöcke wie möglich enthält.
quelle
Jelly , 18 Bytes
Probieren Sie es online!
Nicht effizient - das Beispiel hat 28 Juwelen, die ohne große Ressourcen nicht funktionieren, da der erste Schritt dieser Implementierung darin besteht, eine Liste der 2 27 zu erstellen möglichen Partitionen .
Gibt eine Liste von Listen zurück - die Segmente in der Reihenfolge, in der sie zwischen alternativen Dieben aufgeteilt werden. (Bezüglich der TIO-Ausgabe: Wenn eine Liste nur ein einzelnes Element enthält, stört der implizite Ausdruck die Klammern nicht.
[]
)Wie?
quelle
Mathematica, 118 Bytes
Fast geschlagen Jelly ... nur 1 aus;)
Reine Funktion mit drei Argumenten: Die Kette als Liste von Token wie
{A, A, A, A, B, C, D, B, C, D, B, B}
; die Länge der Kette; und die Anzahl der verschiedenen Juwelen. Es wird eine Liste der Unterlisten im Formular zurückgegeben{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}
, in der die Token ohne negative Vorzeichen an einen Dieb und die Token mit negativen Vorzeichen an den anderen Dieb gehen. (Obwohl dies redundante Informationen sind, führt der Algorithmus zu dieser Darstellung, und das Entfernen der negativen Vorzeichen würde mehrere Bytes kosten.)Zuerst müssen wir eine Funktion implementieren, die eine Liste und eine Menge von
n
Ausschnitten verwendet und die Liste dern+1
Unterlisten zurückgibt, die durch Ausschneiden der Eingabeliste an diesenn
Ausschnitten erhalten werden. Der binäre Infix-Operator±
wird für diesen Zweck verwendet und durch rekursiv definiertl_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};
. Aufgrund des negativen Vorzeichens direkt danachAppend
ist das Ergebnis, dass die Unterlisten abwechselnd negative Vorzeichen haben und nicht mit jedem Token verbunden sind.Dann generieren wir alle möglichen Cut-Place-Sets, deren Länge höchstens der Anzahl der Jewel-Typen entspricht,
Range@#2~Subsets~#3
undi=#;(i±#)&/@
wenden den±
Operator (mit der eingegebenen Jewel- Liste) nacheinander auf jedes dieser Cut-Place-Sets an.Zum Schluss
SelectFirst[...,Tr[Tr/@#]==0&]&
wird die erste der resultierenden Collier-Divisionen ausgewählt, die fair ist. Dies geschieht durch buchstäbliches Aufsummieren aller Elemente in allen Unterlisten. Mathematica ist klug genug, die positiven und negativen Kopien jedes Tokens auf offensichtliche Weise zu löschen.quelle
Pyth, 16 Bytes
Probieren Sie es online aus: Demo oder Test Suite
Erläuterung:
quelle
05AB1E , 14 Bytes
Probieren Sie es online aus oder überprüfen Sie alle Testfälle .
Erläuterung:
quelle