it-swarm.com.de

Wie kann man Socken von einem Stapel effizient koppeln?

Gestern habe ich die Socken aus der sauberen Wäsche gepaart und herausgefunden, wie ich es mache, ist nicht sehr effizient. Ich machte eine naive Suche - ich suchte einen Strumpf und "iterierte" den Stapel, um sein Paar zu finden. Dies erfordert eine Iteration über n/2 * n/4 = n2/ 8 Socken im Durchschnitt.

Als Informatiker dachte ich darüber nach, was ich tun könnte? Das Sortieren (nach Größe/Farbe/...) kam natürlich in den Sinn, um eine O(NlogN)-Lösung zu erzielen.

Hashing oder andere nicht vorhandene Lösungen sind keine Option, da ich meine Socken nicht duplizieren kann (obwohl es schön sein könnte, wenn ich könnte).

Die Frage ist also im Grunde:

Was ist der beste Weg, um bei einem Stapel von n Sockenpaaren, die 2n Elemente enthalten (vorausgesetzt, jede Socke hat genau ein passendes Paar), diese effizient mit bis zu logarithmischem zusätzlichen Platz zu kombinieren? (Ich glaube, ich kann mich bei Bedarf an diese Menge an Informationen erinnern.)

Ich würde mich über eine Antwort freuen, die folgende Aspekte anspricht:

  • Eine allgemeine theoretische Lösung für eine große Anzahl von Socken.
  • Die tatsächliche Anzahl der Socken ist nicht so groß, ich glaube meinem Ehepartner nicht und ich habe mehr als 30 Paare. (Und es ist ziemlich einfach, zwischen meinen und ihren Socken zu unterscheiden. Kann man das auch verwenden?)
  • Entspricht es dem Elementunterscheidungsproblem ?
3815
amit

Sortierlösungen wurden vorgeschlagen, aber Sortieren ist etwas zu viel : Wir brauchen keine Ordnung; Wir brauchen nur Gleichstellungsgruppen .

Also Hashing wäre genug (und schneller).

  1. Bilden Sie für jede Sockenfarbe einen Stapel . Iterieren Sie über alle Socken in Ihrem Eingabekorb und verteilen Sie sie auf die Farbstapel .
  2. Iterieren Sie über jeden Stapel und verteilen Sie ihn durch eine andere Metrik (z. B. Muster) in die zweite Gruppe von Stapeln
  3. Wenden Sie dieses Schema rekursiv an , bis Sie alle Socken auf sehr kleine Stapel verteilt haben, die Sie sofort visuell bearbeiten können

Diese Art der rekursiven Hash-Partitionierung wird tatsächlich von SQL Server ausgeführt, wenn ein Hash-Join oder eine Hash-Aggregation über große Datenmengen erforderlich ist. Es verteilt seinen Build-Eingabestream auf viele Partitionen, die unabhängig sind. Dieses Schema lässt sich linear auf beliebige Datenmengen und mehrere CPUs skalieren.

Sie brauchen keine rekursive Partitionierung, wenn Sie einen Verteilungsschlüssel (Hash-Schlüssel) finden, der genug Buckets bietet, dass jedes Bucket klein genug ist, um sehr verarbeitet zu werden schnell. Leider glaube ich nicht, dass Socken eine solche Eigenschaft haben.

Wenn jede Socke eine Ganzzahl mit dem Namen "PairID" hätte, könnte man sie leicht nach PairID % 10 (der letzten Ziffer) auf 10 Eimer verteilen.

Die beste realistische Partitionierung, die ich mir vorstellen kann, ist die Erstellung eines Rechtecks ​​aus Pfählen : Eine Dimension ist Farbe, die andere ist das Muster. Warum ein Rechteck? Weil wir O(1) zufälligen Zugriff auf Pfähle benötigen. (Ein 3D Quader würde auch funktionieren, aber das ist nicht sehr praktisch.)


Aktualisieren:

Was ist mit Parallelität ? Können sich mehrere Menschen schneller an die Socken anpassen?

  1. Die einfachste Parallelisierungsstrategie besteht darin, mehrere Arbeiter aus dem Eingabekorb zu nehmen und die Socken auf die Stapel zu legen. Dies vergrößert sich nur so sehr - stellen Sie sich 100 Menschen vor, die über 10 Haufen kämpfen. Die Synchronisationskosten (manifestieren sich in Handkollisionen und menschlicher Kommunikation) zerstören Effizienz und Geschwindigkeit (siehe niversal Scalability Law !). Ist dies anfällig für Deadlocks ? Nein, da jeder Arbeiter immer nur auf einen Stapel zugreifen muss. Mit nur einer "Sperre" kann es keine Blockierung geben. Livelocks könnten möglich sein, abhängig davon, wie die Menschen den Zugang zu Pfählen koordinieren. Sie könnten einfach zufälliges Backoff verwenden, wie Netzwerkkarten dies auf physikalischer Ebene tun, um zu bestimmen, welche Karte ausschließlich auf das Netzwerkkabel zugreifen kann. Wenn es für NICs funktioniert, sollte es auch für Menschen funktionieren.
  2. Es ist nahezu unbegrenzt skalierbar, wenn jeder Arbeiter seinen eigenen Stapelsatz hat . Arbeiter können dann große Sockenstücke aus dem Eingabekorb entnehmen (sehr wenig Streit, da sie es selten tun) und sie müssen sich nicht synchronisieren, wenn sie die Socken überhaupt verteilen (weil sie fadenlokale Stapel haben). Am Ende müssen alle Arbeiter ihre Stapel zusammenlegen. Ich glaube, dass dies in O (Protokoll (Arbeiterzahl * Stapel pro Arbeiter)) erfolgen kann, wenn die Arbeiter einen Aggregationsbaum bilden.

Was ist mit dem Elementunterscheidungsproblem ? Wie im Artikel angegeben, kann das Problem der Elementunterscheidbarkeit in O(N) gelöst werden. Dies gilt auch für das Sockenproblem (auch für O(N), wenn Sie nur einen Verteilungsschritt benötigen (ich habe mehrere Schritte vorgeschlagen, nur weil Menschen schlecht im Rechnen sind - ein Schritt reicht aus, wenn Sie auf md5(color, length, pattern, ...) verteilen). dh ein perfekter Hash aller Attribute)).

Offensichtlich kann man nicht schneller gehen als O(N), also haben wir die optimale Untergrenze erreicht.

Obwohl die Ausgaben nicht genau gleich sind (in einem Fall nur ein Boolescher Wert), sind die asymptotischen Komplexitäten gleich.

2392
usr

Da sich die Architektur des menschlichen Gehirns grundlegend von einer modernen CPU unterscheidet, ergibt diese Frage keinen praktischen Sinn.

Menschen können CPU-Algorithmen dadurch überzeugen, dass das Finden eines passenden Paares eine Operation für einen Satz sein kann, der nicht zu groß ist.

Mein Algorithmus:

spread_all_socks_on_flat_surface();
while (socks_left_on_a_surface()) {
     // Thanks to human visual SIMD, this is one, quick operation.
     pair = notice_any_matching_pair();
     remove_socks_pair_from_surface(pair);
}

Zumindest verwende ich das im wirklichen Leben und finde es sehr effizient. Der Nachteil ist, dass es eine flache Oberfläche erfordert, aber es ist in der Regel reichlich vorhanden.

564
dpc.pw

Fall 1 : Alle Socken sind identisch (das mache ich übrigens im wirklichen Leben).

Wähle zwei aus, um ein Paar zu bilden. Konstante Zeit.

Fall 2 : Es gibt eine konstante Anzahl von Kombinationen (Eigentumsrechte, Farbe, Größe, Textur usw.).

Verwenden Sie radix sort . Dies ist nur eine lineare Zeit, da kein Vergleich erforderlich ist.

Fall 3 : Die Anzahl der Kombinationen ist im Voraus nicht bekannt (allgemeiner Fall).

Wir müssen einen Vergleich durchführen, um zu überprüfen, ob zwei Socken paarweise kommen. Wählen Sie einen der auf O(n log n) Vergleichen basierenden Sortieralgorithmen.

In der Praxis funktionieren diese theoretisch optimalen Algorithmen jedoch nicht gut, wenn die Anzahl der Socken relativ klein (konstant) ist. Es kann sogar länger dauern als die sequentielle Suche, für die theoretisch quadratische Zeit erforderlich ist.

250
Terry Li

Nicht algorithmische Antwort, aber "effizient", wenn ich es tue:

  • schritt 1) ​​Entsorgen Sie alle vorhandenen Socken

  • schritt 2) Gehe zu Walmart und kaufe sie in Paketen von 10 - n Paketen von Weiß und m Paketen von Schwarz. Keine Notwendigkeit für andere Farben im Alltag.

Aber manchmal muss ich das wiederholen (verlorene Socken, beschädigte Socken usw.), und ich hasse es, zu oft vollkommen gute Socken wegzuwerfen (und ich wünschte, sie würden weiterhin die gleiche Sockenreferenz verkaufen!), Also habe ich kürzlich genommen Ein anderer Versuch.

Algorithmische Antwort:

Bedenken Sie, dass Ihre Chancen, bei einer naiven Suche die passende Socke zu finden, ziemlich gering sind, als wenn Sie nur eine Socke für den zweiten Sockenstapel ziehen.

  • Nimm also zufällig fünf davon und merke dir ihre Form oder Länge.

Warum fünf? Normalerweise sind Menschen gut darin, sich zwischen fünf und sieben verschiedene Elemente im Arbeitsspeicher zu merken - ein bisschen wie das menschliche Äquivalent von RPN stack - five ist eine sichere Standardeinstellung.

  • Nimm einen aus dem Stapel von 2n-5.

  • Suchen Sie nun nach einer Übereinstimmung (visueller Mustervergleich - Menschen können das mit einem kleinen Stapel) innerhalb der fünf, die Sie gezeichnet haben. Wenn Sie keine finden, fügen Sie diese zu Ihren fünf hinzu.

  • Nimm zufällig Socken vom Stapel und vergleiche sie mit deinen 5 + 1 Socken für ein Match. Wenn Ihr Stack wächst, verringert dies Ihre Leistung, erhöht jedoch Ihre Gewinnchancen. Viel schneller.

Notieren Sie sich die Formel, um zu berechnen, wie viele Proben Sie für eine 50% ige Quote eines Matches ziehen müssen. IIRC ist ein hypergeometrisches Gesetz.

Ich mache das jeden Morgen und brauche selten mehr als drei Ziehungen - aber ich habe n ähnliche Paare (ungefähr 10, gebe oder nehme die verlorenen) von m geformten weißen Socken. Jetzt können Sie die Größe meines Lagerbestands abschätzen :-)

Übrigens , ich fand heraus, dass die Summe der Transaktionskosten für das Sortieren aller Socken jedes Mal, wenn ich ein Paar benötigte, weitaus geringer war als für das einmalige und einmalige die Socken binden. Just-in-Time funktioniert besser, weil Sie dann die Socken nicht binden müssen und es auch eine abnehmende marginale Rendite gibt (das heißt, Sie halten nach den zwei oder drei Socken Ausschau, die Sie irgendwo in der Wäsche haben und brauchen) Um das Anpassen deiner Socken zu beenden, verlierst du Zeit.

154
guylhem

Ich nehme die erste Socke und lege sie ab (etwa auf den Rand der Wäscheschüssel). Dann nehme ich eine andere Socke und überprüfe, ob es die gleiche ist wie die erste Socke. Wenn ja, entferne ich beide. Wenn nicht, lege ich es neben die erste Socke. Dann nehme ich die dritte Socke und vergleiche sie mit den ersten beiden (wenn sie noch da sind). Usw.

Dieser Ansatz kann ziemlich einfach in einem Array implementiert werden, vorausgesetzt, dass das "Entfernen" von Socken eine Option ist. Eigentlich müssen Sie nicht einmal Socken "ausziehen". Wenn Sie die Socken nicht sortieren müssen (siehe unten), können Sie sie einfach verschieben und erhalten ein Array, in dem alle Socken paarweise im Array angeordnet sind.

Unter der Annahme, dass der einzige Vorgang für Socken der Vergleich auf Gleichheit ist, ist dieser Algorithmus im Grunde immer noch ein n2 Algorithmus, obwohl ich den Durchschnittsfall nicht kenne (habe nie gelernt, das zu berechnen).

Das Sortieren verbessert natürlich die Effizienz, insbesondere im wirklichen Leben, wo Sie leicht eine Socke zwischen zwei andere Socken "stecken" können. Beim Rechnen könnte dasselbe durch einen Baum erreicht werden, aber das ist zusätzlicher Platz. Und natürlich sind wir wieder bei NlogN (oder ein bisschen mehr, wenn es mehrere Socken gibt, die nach Sortierkriterien gleich sind, aber nicht vom selben Paar).

Ansonsten fällt mir nichts ein, aber diese Methode scheint im wirklichen Leben ziemlich effizient zu sein. :)

102
Vilx-

Das ist die falsche Frage. Die richtige Frage lautet: Warum verbringe ich Zeit damit, Socken zu sortieren? Wie viel kostet es auf Jahresbasis, wenn Sie Ihre Freizeit für X Geldeinheiten Ihrer Wahl einschätzen?

Und meistens ist dies nicht nur irgendeine Freizeit, es ist Morgen Freizeit, die Sie vielleicht im Bett verbringen, an Ihrem Kaffee nippen oder etwas früher abreisen und nicht im Verkehr hängen bleiben.

Es ist oft gut, einen Schritt zurückzutreten und das Problem zu umgehen.

Und es gibt einen Weg!

Finde eine Socke, die du magst. Berücksichtigen Sie alle relevanten Merkmale: Farbe bei unterschiedlichen Lichtverhältnissen, allgemeine Qualität und Haltbarkeit, Komfort bei unterschiedlichen klimatischen Bedingungen und Geruchsabsorption. Wichtig ist auch, dass sie bei der Lagerung nicht an Elastizität verlieren. Daher sind natürliche Stoffe gut und sollten in einer Plastikhülle erhältlich sein.

Es ist besser, wenn es keinen Unterschied zwischen linken und rechten Fußsocken gibt, aber es ist nicht kritisch. Wenn die Strümpfe von links nach rechts symmetrisch sind, ist das Finden eines Paares eine O(1) - Operation, und das Sortieren der Strümpfe ist eine ungefähre O(M) - Operation, wobei M die Anzahl der Plätze in Ihrem Haus ist, die Sie haben mit Socken übersät, idealerweise mit einer kleinen konstanten Zahl.

Wenn Sie ein ausgefallenes Paar mit einer anderen linken und einer anderen rechten Socke ausgewählt haben, nehmen Sie für eine vollständige Eimersortierung der linken und rechten Fußschalen O (N + M), wobei N die Anzahl der Socken und M die gleiche wie oben ist. Jemand anderes kann die Formel für durchschnittliche Iterationen des Findens des ersten Paares angeben, aber der schlechteste Fall für das Finden eines Paares mit blinder Suche ist N/2 + 1, was für vernünftiges N astronomisch unwahrscheinlich ist. Dies kann durch Verwendung eines erweiterten Bildes beschleunigt werden Erkennungsalgorithmen und Heuristiken beim Scannen des Stapels unsortierter Socken mit Mk1 Eyeball .

Ein Algorithmus zum Erreichen der O(1) - Sockenpaarungseffizienz (unter der Annahme einer symmetrischen Socke) lautet also:

  1. Sie müssen abschätzen, wie viele Paar Socken Sie für den Rest Ihres Lebens benötigen, oder bis Sie in den Ruhestand gehen und in ein wärmeres Klima ziehen, ohne dass Sie jemals wieder Socken tragen müssen. Wenn Sie jung sind, können Sie auch abschätzen, wie lange es dauert, bis wir alle Socken-Sortierroboter in unseren Häusern haben, und das ganze Problem wird irrelevant.

  2. Sie müssen herausfinden, wie Sie Ihre ausgewählte Socke in loser Schüttung bestellen können, wie viel sie kostet und ob sie geliefert wird.

  3. Bestellen Sie die Socken!

  4. Lass deine alten Socken los.

Ein alternativer Schritt 3 würde beinhalten, die Kosten für den Kauf der gleichen Menge vielleicht billigerer Socken über die Jahre hinweg paarweise zu vergleichen und die Kosten für das Sortieren von Socken zu addieren, aber nehmen Sie mein Wort: Kaufen in loser Schüttung ist billiger! Außerdem steigt der Wert von Lagersocken mit der Inflationsrate des Aktienkurses, die höher ist als bei vielen Investitionen. Andererseits gibt es auch Lagerkosten, aber Socken nehmen im obersten Regal eines Kleiderschranks wirklich nicht viel Platz ein.

Problem gelöst. Also, holen Sie sich einfach neue Socken, werfen Sie Ihre alten weg/spenden Sie sie und leben Sie glücklich, wenn Sie wissen, dass Sie für den Rest Ihres Lebens jeden Tag Geld und Zeit sparen.

58
hyde

Die theoretische Grenze ist O(n), weil Sie jede Socke anfassen müssen (es sei denn, einige sind bereits irgendwie gepaart).

Sie können O(n) mit radix sort erreichen. Sie müssen nur einige Attribute für die Eimer auswählen.

  1. Zuerst kannst du wählen (ihre, meine) - teile sie in 2 Stapel auf,
  2. verwenden Sie dann Farben (können eine beliebige Reihenfolge für die Farben haben, z. B. alphabetisch nach Farbnamen) - Teilen Sie sie nach Farben in Stapel auf (denken Sie daran, die ursprüngliche Reihenfolge von Schritt 1 für alle Socken in demselben Stapel beizubehalten).
  3. dann Länge der Socke,
  4. dann Textur, ....

Wenn Sie eine begrenzte Anzahl von Attributen auswählen können, aber genug Attribute, um jedes Paar eindeutig zu identifizieren, sollten Sie O (k * n) eingeben. Dies ist O(n), wenn wir k für möglich halten begrenzt.

49
andredor

Als praktische Lösung:

  1. Stellen Sie schnell Stapel von leicht unterscheidbaren Socken her. (Sprich nach Farbe)
  2. Quicksortiere jeden Stapel und nutze die Länge der Socke zum Vergleich. Als Mensch können Sie ziemlich schnell entscheiden, welche Socke zur Partitionierung verwendet werden soll, um den schlimmsten Fall zu vermeiden. (Sie können mehrere Socken gleichzeitig sehen, nutzen Sie das zu Ihrem Vorteil!)
  3. Hören Sie auf, Stapel zu sortieren, wenn sie eine Schwelle erreicht haben, bei der Sie sofort Spot-Paare und unpaarbare Socken finden können

Wenn Sie 1000 Socken mit 8 Farben und einer durchschnittlichen Verteilung haben, können Sie 4 Stapel von jeweils 125 Socken in kürzester Zeit herstellen. Mit einer Schwelle von 5 Socken können Sie jeden Stapel in 6 Läufen sortieren. (Zählen Sie 2 Sekunden, um eine Socke auf den richtigen Haufen zu werfen. Das dauert weniger als 4 Stunden.)

Wenn Sie nur 60 Socken, 3 Farben und 2 Arten von Socken (Ihre/Ihre Frau) haben, können Sie jeden Stapel von 10 Socken in 1 Durchgängen sortieren (Wieder Schwellenwert = 5). (Zählen von 2 Sekunden dauert es 2 Minuten).

Die anfängliche Eimersortierung beschleunigt Ihren Prozess, da sie Ihre n Socken in der c*n -Zeit in k Eimer aufteilt, so dass Sie nur noch c*n*log(k) arbeiten müssen. (Ohne Berücksichtigung der Schwelle). Alles in allem tun Sie also etwas für n*c*(1 + log(k)), wobei c die Zeit ist, eine Socke auf einen Stapel zu werfen.

Dieser Ansatz ist im Vergleich zu jeder c*x*n + O(1)-Methode ungefähr so ​​lange vorteilhaft wie log(k) < x - 1.


In der Informatik kann dies hilfreich sein: Wir haben eine Sammlung von n Dingen, eine Reihenfolge (Länge) und auch eine Äquivalenzbeziehung (zusätzliche Informationen, zum Beispiel die Farbe von Socken). Die Äquivalenzbeziehung ermöglicht es uns, eine Unterteilung der ursprünglichen Sammlung vorzunehmen, und in jeder Äquivalenzklasse bleibt unsere Reihenfolge erhalten. Die Zuordnung eines Ding zu seiner Äquivalenzklasse kann in O (1) erfolgen, sodass nur O(n) erforderlich ist, um jedes Element einer Klasse zuzuweisen. Jetzt haben wir unsere zusätzlichen Informationen verwendet und können auf jede Art und Weise vorgehen, um jede Klasse zu sortieren. Der Vorteil ist, dass die Datensätze bereits deutlich kleiner sind.

Die Methode kann auch verschachtelt werden, wenn wir mehrere Äquivalenzbeziehungen haben -> Farbstapel erstellen, als innerhalb jeder Stapelpartition auf Textur, als nach Länge sortieren. Jede Äquivalenzbeziehung, die eine Partition mit mehr als 2 Elementen mit ungefähr gleicher Größe erstellt, führt zu einer schnelleren Sortierung (vorausgesetzt, wir können ihrem Stapel direkt einen Strumpf zuweisen), und die Sortierung kann bei kleineren Datenmengen sehr schnell erfolgen.

31
Samuel

Sie versuchen das falsche Problem zu lösen.

Lösung 1: Jedes Mal, wenn Sie schmutzige Socken in Ihren Wäschekorb legen, binden Sie sie zu einem kleinen Knoten zusammen. Auf diese Weise müssen Sie nach dem Waschen nicht mehr sortieren. Stellen Sie sich das vor, als würden Sie einen Index in einer Mongo-Datenbank registrieren. Ein wenig Arbeit voraus für einige CPU-Einsparungen in der Zukunft.

Lösung 2: Wenn es Winter ist, müssen Sie keine passenden Socken tragen. Wir sind Programmierer. Niemand muss es wissen, solange es funktioniert.

Lösung 3: Verbreiten Sie die Arbeit. Sie möchten einen solch komplexen CPU-Prozess asynchron ausführen, ohne die Benutzeroberfläche zu blockieren. Nimm diesen Haufen Socken und stopfe sie in eine Tasche. Suchen Sie nach einem Paar nur, wenn Sie es brauchen. Auf diese Weise ist der Arbeitsaufwand weitaus geringer.

Hoffe das hilft!

26
Nikolay Dyankov

Diese Frage ist eigentlich zutiefst philosophisch. Im Kern geht es darum, ob die Fähigkeit der Menschen, Probleme zu lösen (die "Wetware" unseres Gehirns) der Leistung von Algorithmen entspricht.

Ein offensichtlicher Algorithmus für das Sortieren von Socken ist:

Let N be the set of socks that are still unpaired, initially empty
for each sock s taken from the dryer
  if s matches a sock t in N
    remove t from N, bundle s and t together, and throw them in the basket
  else
    add s to N

In der Informatik dreht sich bei diesem Problem alles um die einzelnen Schritte

  1. msgstr "wenn s mit einer Socke t in N gepaart ist". Wie schnell können wir uns "erinnern", was wir bisher gesehen haben?
  2. "entferne t von N" und "füge s zu N hinzu". Wie teuer ist es, den Überblick zu behalten, was wir bisher gesehen haben?

Der Mensch wird verschiedene Strategien anwenden, um dies zu bewirken. Menschliches Gedächtnis ist assoziativ , so etwas wie eine Hash-Tabelle, in der Merkmalssätze gespeicherter Werte mit den entsprechenden Werten selbst gepaart werden. Zum Beispiel ist das Konzept "rotes Auto" auf alle roten Autos abgebildet, an die sich eine Person erinnern kann. Jemand mit einem perfekten Gedächtnis hat eine perfekte Abbildung. Die meisten Menschen sind in dieser Hinsicht unvollkommen (und die meisten anderen). Die assoziative Karte hat eine begrenzte Kapazität. Zuordnungen können unter verschiedenen Umständen (ein Bier zuviel) aus der Existenz geraten , irrtümlich aufgezeichnet werden ("Ich dachte, ihr Name war Betty, nicht Nettie") oder niemals überschrieben werden obwohl wir beobachten, dass sich die Wahrheit geändert hat ("Papas Auto" erinnert an "orangefarbenen Feuervogel", als wir tatsächlich wussten, dass er das gegen den roten Camaro eingetauscht hatte).

Bei Socken bedeutet perfekter Rückruf, dass beim Betrachten einer Socke s immer die Erinnerung an ihre Geschwister t angezeigt wird, einschließlich genügend Informationen (wo sie sich auf dem Bügelbrett befinden), um t zu lokalisieren. in konstanter Zeit. Eine Person mit fotografischem Gedächtnis schafft sowohl 1 als auch 2 in konstanter Zeit ohne Fehler.

Jemand mit weniger als perfektem Gedächtnis verwendet möglicherweise ein paar Äquivalenzklassen für gesunden Menschenverstand, die auf den Merkmalen seiner Fähigkeit basieren: Größe (Papa, Mama, Baby), Farbe (grünlich, rötlich usw.), Muster (Rautenmuster, normal usw.). , style (footie, kniehoch, etc.). So würde das Bügelbrett in Abschnitte für die Kategorien unterteilt. Dies ermöglicht es normalerweise, die Kategorie in konstanter Zeit nach Speicher zu lokalisieren, aber dann ist eine lineare Suche durch die Kategorie "Bucket" erforderlich.

Jemand, der überhaupt kein Gedächtnis oder keine Vorstellungskraft hat (sorry), wird einfach die Socken auf einem Stapel halten und eine lineare Suche über den gesamten Stapel durchführen.

Ein ordentlicher Freak könnte, wie jemand vorschlug, numerische Bezeichnungen für Paare verwenden. Dies öffnet die Tür zu einer vollständigen Bestellung, die es dem Menschen ermöglicht, genau dieselben Algorithmen zu verwenden, die wir mit einer CPU verwenden könnten: binäre Suche, Bäume, Hashes usw.

Der "beste" Algorithmus hängt also von den Qualitäten der Wetware/Hardware/Software ab, auf der er ausgeführt wird, und von unserer Bereitschaft, zu "betrügen", indem wir Paaren eine Gesamtreihenfolge auferlegen. Ein "bester" Meta - Algorithmus ist es, den weltbesten Sockensortierer einzustellen: eine Person oder Maschine, die eine riesige Menge N von Sockenattributsätzen in a erfassen und schnell speichern kann 1-1 Assoziativspeicher mit konstanter Zeit zum Nachschlagen, Einfügen und Löschen. Solche Menschen und Maschinen können beschafft werden. Wenn Sie eine haben, können Sie alle Socken in O(N) Zeit für N Paare koppeln, was optimal ist. Mit den Gesamtbestellungs-Tags können Sie Standard-Hashing verwenden, um das gleiche Ergebnis mit einem menschlichen oder einem Hardware-Computer zu erzielen.

25
Gene

Kosten: Socken bewegen -> hoch, Socken in einer Reihe finden/suchen -> klein

Was wir tun wollen, ist die Anzahl der Züge zu reduzieren und mit der Anzahl der Suchen zu kompensieren. Wir können auch die Multithred-Umgebung des Homo Sapiens nutzen, um mehr Dinge im Entscheidungs-Cache zu speichern.

X = Ihre, Y = Ihre Ehepartner

Von Stapel A aller Socken:

Wählen Sie zwei Socken, setzen Sie die entsprechende X-Socke in die X-Linie und die Y-Socke in die Y-Linie an der nächsten verfügbaren Position.

Mach so lange, bis A leer ist.

Für jede Zeile X und Y

  1. Wählen Sie die erste Socke in der Linie und suchen Sie entlang der Linie, bis die entsprechende Socke gefunden wird.

  2. In die entsprechende fertige Sockenreihe stecken.

  3. Optional Wenn Sie die Zeile durchsuchen und die aktuelle Socke, die Sie ansehen, mit der vorherigen identisch ist, führen Sie Schritt 2 für diese Socken aus.

Optional können Sie in Schritt 1 zwei Socken aus dieser Zeile anstelle von zwei auswählen, da der Cachespeicher groß genug ist, um schnell feststellen zu können, ob eine der beiden Socken mit der aktuellen in der betrachteten Zeile übereinstimmt. Wenn Sie das Glück haben, drei Arme zu haben, können Sie möglicherweise drei Socken gleichzeitig analysieren, vorausgesetzt, die Erinnerung an das Motiv ist groß genug.

Tun Sie dies, bis sowohl X als auch Y leer sind.

Getan

Da dies jedoch eine ähnliche Komplexität wie die Auswahlsortierung hat, ist der Zeitaufwand aufgrund der E/A-Geschwindigkeit (Verschieben von Socken) und der Suchgeschwindigkeit (Durchsuchen der Zeile nach einer Socke) weitaus geringer.

20
1-----1

Hier ist eine Omega (n log n) -Untergrenze im vergleichsbasierten Modell. (Die einzige gültige Operation ist das Vergleichen von zwei Socken.)

Angenommen, Sie wissen , dass Ihre 2n-Socken folgendermaßen angeordnet sind:

p1 p2 p3 ... pn pf(1) pf(2) ... pf(n)

dabei ist f eine unbekannte Permutation der Menge {1,2, ..., n}. Das zu wissen, kann das Problem nicht schwerer machen. Es gibt n! mögliche Ausgaben (Übereinstimmungen zwischen der ersten und zweiten Hälfte), dh Sie benötigen log (n!) = Omega (n log n) Vergleiche. Dies ist durch Sortieren erreichbar.

Da Sie an Verbindungen zum Problem der Elementunterscheidbarkeit interessiert sind, ist es schwieriger, die für die Elementunterscheidbarkeit festgelegte Omega (n log n) zu beweisen, da die Ausgabe binär Ja/Nein ist. Hier muss die Ausgabe übereinstimmen, und die Anzahl der möglichen Ausgaben reicht aus, um eine angemessene Grenze zu erhalten. Es gibt jedoch eine Variante, die mit der Unterscheidbarkeit von Elementen zusammenhängt. Nehmen wir an, Sie erhalten 2n Socken und fragen sich, ob sie eindeutig gepaart werden können. Sie können eine Ermäßigung von ED erhalten, indem Sie (a1, ein2, ..., einn) zu einem1, ein1, ein2, ein2, ..., einn, einn). (In Klammern ist der Nachweis der ED-Härte sehr interessant, über Topologie .)

Ich denke, dass es ein Omega geben sollte (n2) für das ursprüngliche Problem gebunden, wenn Sie nur Gleichheitstests zulassen. Meine Intuition ist: Betrachten Sie ein Diagramm, in dem Sie nach einem Test eine Kante hinzufügen, und argumentieren Sie, dass die Ausgabe nicht eindeutig bestimmt wird, wenn das Diagramm nicht dicht ist.

20
sdcvvc

So mache ich das eigentlich für p Paar Socken (n = 2p einzelne Socken):

  • Nimm zufällig eine Socke vom Stapel.
  • Für die erste Socke oder wenn alle zuvor ausgewählten Socken gepaart wurden, platzieren Sie die Socke einfach in den ersten "Schlitz" einer "Reihe" ungepaarter Socken vor Ihnen.
  • Wenn Sie eine oder mehrere ausgewählte ungepaarte Socken haben, vergleichen Sie Ihre aktuelle Socke mit allen ungepaarten Socken im Array.
    • Es ist möglich, Socken in allgemeine Klassen oder Typen (weiß/schwarz, Knöchel/Crew, Athletik/Kleidung) zu unterteilen, wenn Sie Ihr Array zusammenstellen.
    • Wenn Sie eine akzeptable Übereinstimmung finden, setzen Sie beide Socken zusammen und entfernen Sie sie aus dem Array.
    • Wenn Sie dies nicht tun, stecken Sie die aktuelle Socke in den ersten freien Steckplatz im Array.
  • Wiederholen Sie mit jeder Socke.

Das Worst-Case-Szenario dieses Schemas ist, dass jedes Paar Socken so unterschiedlich ist, dass es genau übereinstimmt und dass die ersten n/2 Socken, die Sie auswählen, alle unterschiedlich sind. Dies ist dein O (n2) Szenario, und es ist extrem unwahrscheinlich. Wenn die Anzahl der eindeutigen Arten von Socken t geringer ist als die Anzahl der Paare p = n/2 und die Socken in jeder Art gleich sind (normalerweise in Trage- verwandte Begriffe), dass jede Socke dieses Typs mit jeder anderen gepaart werden kann. Wie ich oben schlussfolgerte, beträgt die maximale Anzahl von Socken, mit denen Sie jemals vergleichen müssen, t, danach die nächste Zieh wird passend zu einer der ungepaarten Socken. Dieses Szenario ist in der durchschnittlichen Sockenschublade viel wahrscheinlicher als im schlimmsten Fall und reduziert die Komplexität im schlimmsten Fall auf O (n * t), wobei normalerweise t << n.

18
KeithS

Realer Ansatz:

Nehmen Sie so schnell wie möglich die Socken nacheinander vom unsortierten Stapel und legen Sie sie in Stapel vor sich ab. Die Stapel sollten platzsparend angeordnet sein, wobei alle Socken in die gleiche Richtung weisen. Die Anzahl der Pfähle ist durch die Entfernung begrenzt, die Sie leicht erreichen können. Die Auswahl eines Stapels, auf den eine Socke gelegt werden soll, sollte - so schnell wie möglich - durch Anlegen einer Socke auf einem Stapel offenbar gleichartiger Socken erfolgen. Der gelegentliche Fehler vom Typ I (eine Socke auf einen Stapel legen, zu dem sie nicht gehört) oder vom Typ II (eine Socke auf einen eigenen Stapel legen, wenn ein Stapel ähnlicher Socken vorhanden ist) kann toleriert werden. Die wichtigste Überlegung ist: Geschwindigkeit. Sobald alle Socken gestapelt sind, gehen Sie schnell die Mehrfachsockenstapel durch, um Paare zu bilden und sie zu entfernen (diese gehen in Richtung der Schublade). Wenn der Stapel nicht übereinstimmende Socken enthält, stapeln Sie sie wieder auf den besten (innerhalb des schnellstmöglichen Beschränkungsstapels). Wenn alle Mehrsockenstapel verarbeitet wurden, passen Sie die verbleibenden paarbaren Socken an, die aufgrund von Fehlern vom Typ II nicht gepaart wurden. Wusch, du bist fertig - und ich habe viele Socken und wasche sie nicht, bis ein großer Teil schmutzig ist. Ein weiterer praktischer Hinweis: Ich klappe die Oberseite einer Socke über die andere und nutze ihre elastischen Eigenschaften, damit sie zusammen bleiben, während sie in die Schublade und in die Schublade transportiert werden.

16
Jim Balter

Aus Ihrer Frage geht hervor, dass Sie nicht viel Erfahrung mit Wäsche haben :). Sie benötigen einen Algorithmus, der mit einer kleinen Anzahl von nicht paarbaren Socken gut funktioniert.

Die bisherigen Antworten nutzen unsere Fähigkeiten zur Erkennung menschlicher Muster nicht gut aus. Das Set-Spiel gibt einen Hinweis darauf, wie dies gut funktioniert: Legen Sie alle Socken in einen zweidimensionalen Raum, damit Sie sie gut erkennen und mit Ihren Händen leicht erreichen können. Dies begrenzt Sie auf einen Bereich von etwa 120 × 80 cm. Wählen Sie dort die Paare aus, die Sie erkennen, und entfernen Sie sie. Legen Sie zusätzliche Socken in den freien Raum und wiederholen Sie. Wenn Sie sich für Leute mit leicht erkennbaren Socken waschen (kleine Kinder fallen Ihnen ein), können Sie eine gründliche Sortierung durchführen, indem Sie zuerst diese Socken auswählen. Dieser Algorithmus funktioniert nur gut, wenn die Anzahl der Einzelsocken niedrig ist

14

Nimm eine erste Socke und lege sie auf einen Tisch. Jetzt nimm eine andere Socke; Wenn es mit dem zuerst ausgewählten übereinstimmt, platzieren Sie es oben auf dem ersten. Wenn nicht, legen Sie es in geringem Abstand vom ersten auf den Tisch. Nimm eine dritte Socke. Wenn es mit einem der beiden vorherigen übereinstimmt, platzieren Sie es darüber oder in geringem Abstand zum dritten. Wiederholen, bis Sie alle Socken aufgenommen haben.

14
Justin Fay

Um zu sagen, wie effizient es ist, Socken von einem Stapel zu koppeln, müssen wir zuerst die Maschine definieren, da das Koppeln weder von einer Maschine mit wahlfreiem Zugriff noch von einer Maschine mit wahlfreiem Zugriff durchgeführt wird, die normalerweise als Grundlage für einen Stapel verwendet wird algorithmische Analyse.

Die Maschine

Die Maschine ist eine Abstraktion eines Elements der realen Welt, das als Mensch bezeichnet wird. Es ist in der Lage, über ein Paar Augen aus der Umgebung zu lesen. Und unser Maschinenmodell ist in der Lage, die Umgebung mit zwei Armen zu manipulieren. Logische und arithmetische Operationen werden mit unserem Gehirn berechnet (hoffentlich ;-)).

Wir müssen auch die intrinsische Laufzeit der atomaren Operationen berücksichtigen, die mit diesen Instrumenten durchgeführt werden können. Operationen, die von einem Arm oder Auge ausgeführt werden, weisen aufgrund physikalischer Einschränkungen eine nicht konstante zeitliche Komplexität auf. Das liegt daran, dass wir weder einen endlos großen Sockenstapel mit einem Arm bewegen können, noch dass ein Auge den oberen Sockenstapel auf einem endlos großen Sockenstapel sehen kann.

Die mechanische Physik gibt uns jedoch auch einige Vorteile. Wir sind nicht darauf beschränkt, höchstens eine Socke mit einem Arm zu bewegen. Wir können ein ganzes Paar auf einmal bewegen.

Abhängig von der vorherigen Analyse sollten daher die folgenden Operationen in absteigender Reihenfolge ausgeführt werden:

  • logische und arithmetische Operationen
  • umwelt liest
  • umgebungsmodifikationen

Wir können auch die Tatsache nutzen, dass die Menschen nur eine sehr begrenzte Anzahl von Socken haben. So kann eine Umweltänderung alle Socken im Stapel mit einbeziehen.

Der Algorithmus

Also hier ist mein Vorschlag:

  1. Verteile alle Socken auf dem Haufen über dem Boden.
  2. Finde ein Paar, indem du dir die Socken auf dem Boden ansiehst.
  3. Wiederholen Sie ab 2, bis kein Paar mehr hergestellt werden kann.
  4. Wiederholen Sie von 1 bis es keine Socken mehr auf dem Boden gibt.

Operation 4 ist notwendig, da beim Ausbreiten von Socken einige Socken andere verstecken können. Hier ist die Analyse des Algorithmus:

Die Analyse

Der Algorithmus wird mit hoher Wahrscheinlichkeit beendet. Dies liegt an der Tatsache, dass man in Schritt 2 keine Sockenpaare finden kann.

Für die folgende Laufzeitanalyse der Paarung von n Sockenpaaren nehmen wir an, dass mindestens die Hälfte der 2n Socken nach Schritt 1 nicht ausgeblendet ist. Im Durchschnitt können wir also n/2 Paare finden. Dies bedeutet, dass die Schleife in Schritt 4 O(log n)-mal ausgeführt wird. Schritt 2 wird O(n^2) mal ausgeführt. Daraus können wir schließen:

  • Der Algorithmus beinhaltet O(ln n + n) Umgebungsmodifikationen (Schritt 1 O(ln n) plus Auswahl jedes Paar Socken vom Boden)
  • Der Algorithmus beinhaltet O(n^2) Umgebungslesevorgänge ab Schritt 2
  • Der Algorithmus beinhaltet O(n^2) logische und arithmetische Operationen zum Vergleichen einer Socke mit einer anderen in Schritt 2

Wir haben also eine Gesamtlaufzeitkomplexität von O(r*n^2 + w*(ln n + n)) wobei r und w die Faktoren für Umgebungslese- bzw. Umgebungsschreibvorgänge für eine angemessene Anzahl von Socken sind. Die Kosten für die logischen und arithmetischen Operationen werden weggelassen, da angenommen wird, dass eine konstante Menge an logischen und arithmetischen Operationen erforderlich ist, um zu entscheiden, ob zwei Socken zum selben Paar gehören. Dies ist möglicherweise nicht in jedem Szenario möglich.

12
SpaceTrucker

Ich kam mit einer anderen Lösung heraus, die weder weniger Operationen noch weniger Zeitaufwand versprach, aber es sollte versucht werden, zu prüfen, ob es eine Heuristik ist, die ausreicht, um bei großen Serien von Sockenpaarungen weniger Zeit zu verbrauchen.

Vorraussetzungen: Es gibt keine Garantie, dass es die gleichen Socken gibt. Wenn sie dieselbe Farbe haben, heißt das nicht, dass sie dieselbe Größe oder dasselbe Muster haben. Die Socken werden nach dem Zufallsprinzip gemischt. Es kann eine ungerade Anzahl von Socken geben (einige fehlen, wir wissen nicht wie viele). Bereiten Sie sich darauf vor, eine Variable "index" zu speichern und auf 0 zu setzen.

Das Ergebnis hat ein oder zwei Stapel: 1. "Matched" und 2. "Fehlend"

Heuristik:

  1. Finde die markanteste Socke.
  2. Finden Sie seine Übereinstimmung.
  3. Wenn es keine Übereinstimmung gibt, lege sie auf den "fehlenden" Stapel.
  4. Wiederholen Sie von 1. bis es keine markantesten Socken mehr gibt.
  5. Wenn es weniger als 6 Socken gibt, gehe zu 11.
  6. Paaren Sie blind alle Socken mit dem Nachbarn (nicht einpacken)
  7. Finde alle passenden Paare, packe sie und verschiebe die gepackten Paare auf einen "passenden" Stapel. Wenn keine neuen Übereinstimmungen vorhanden sind, erhöhen Sie "Index" um 1
  8. Wenn "index" größer als 2 ist (dies kann ein Wert sein, der von der Sockenanzahl abhängt, da bei einer größeren Anzahl von Socken die Wahrscheinlichkeit geringer ist, dass sie blind miteinander verbunden werden), fahren Sie mit 11 fort
  9. Mische den Rest
  10. Gehe zu 1
  11. "Index" vergessen
  12. Nimm eine Socke
  13. Finde sein Paar
  14. Wenn es kein Paar für die Socke gibt, lege es auf den "fehlenden" Stapel
  15. Wenn du ein passendes Paar gefunden hast, packe es zusammen und lege es auf den "passenden" Stapel
  16. Wenn es noch mehr Socken gibt, gehen Sie zu 12
  17. Wenn nur noch eine übrig ist, gehe zu 14
  18. Lächeln zufrieden :)

Es könnte auch eine Überprüfung auf beschädigte Socken hinzugefügt werden, als ob diese entfernt würden. Es könnte zwischen 2 und 3 und zwischen 13 und 14 eingefügt werden.

Ich freue mich auf Ihre Erfahrungen und Korrekturen.

12
Sasa
List<Sock> UnSearchedSocks = getAllSocks();
List<Sock> UnMatchedSocks = new list<Sock>();
List<PairOfSocks> PairedSocks = new list<PairOfSocks>();

foreach (Sock newSock in UnsearchedSocks)
{
  Sock MatchedSock = null;
  foreach(Sock UnmatchedSock in UnmatchedSocks)
  {
    if (UnmatchedSock.isPairOf(newSock))
    {
      MatchedSock = UnmatchedSock;
      break;
    }
  }
  if (MatchedSock != null)
  {
    UnmatchedSocks.remove(MatchedSock);
    PairedSocks.Add(new PairOfSocks(MatchedSock, NewSock));
  }
  else
  {
    UnmatchedSocks.Add(NewSock);
  }
}
12
Chad

Wenn ich Socken sortiere, mache ich eine ungefähre radix sort , wobei ich Socken in die Nähe von anderen Socken der gleichen Farbe/Mustertyp fallen lasse. Außer in dem Fall, dass ich eine genaue Übereinstimmung an/in der Nähe der Stelle sehe, an der ich die Socke fallen lassen werde, extrahiere ich das Paar an dieser Stelle.

Fast alle anderen Algorithmen (einschließlich die Antwort mit der höchsten Punktzahl von usr ) sortieren und entfernen dann Paare. Ich finde, als Mensch ist es besser, die Anzahl der Socken, die gleichzeitig in Betracht gezogen werden, zu minimieren.

Ich mache das durch:

  1. Wählen Sie eine markante Socke (was mir zuerst auffällt).
  2. Starten einer Radix-Sortierung von dieser konzeptionellen Position aus, indem Socken aus dem Stapel gezogen werden, basierend auf der Ähnlichkeit zu dieser.
  3. Platzieren Sie die neue Socke in der Nähe des aktuellen Stapels. Der Abstand richtet sich nach dem Unterschied. Wenn Sie feststellen, dass Sie die Socke auf eine andere setzen, weil sie identisch ist, bilden Sie das Paar dort und entfernen Sie sie. Dies bedeutet, dass zukünftige Vergleiche weniger Aufwand erfordern, um den richtigen Ort zu finden.

Dies nutzt die Fähigkeit des Menschen zum Fuzzy-Matching in O(1) Zeit, was in etwa der Erstellung einer Hash-Map auf einem Computergerät entspricht.

Wenn Sie zuerst an den markanten Socken ziehen, können Sie zunächst die weniger markanten Merkmale "vergrößern".

Nachdem Sie die Farbe Fluro, die gestreiften Socken und die drei langen Sockenpaare entfernt haben, erhalten Sie möglicherweise überwiegend weiße Socken, die grob nach ihrer Abnutzung sortiert sind.

Irgendwann sind die Unterschiede zwischen den Socken so gering, dass andere den Unterschied nicht bemerken und keine weiteren Anpassungsmaßnahmen erforderlich sind.

11
Andrew Hill

Wenn Sie eine Socke in die Hand nehmen, legen Sie sie an einen Ort. Dann die nächste Socke, die Sie abholen. Wenn sie nicht zur ersten Socke passt, legen Sie sie neben die erste. Wenn ja, gibt es ein Paar. Auf diese Weise spielt es keine Rolle, wie viele Kombinationen es gibt, und es gibt nur zwei Möglichkeiten für jede Socke, die Sie auswählen - entweder hat sie eine Übereinstimmung, die sich bereits in Ihrem Sockenarray befindet, oder nicht, was bedeutet, dass Sie Fügen Sie es einem Bereich im Array hinzu.

Dies bedeutet auch, dass Sie mit ziemlicher Sicherheit nie alle Ihre Socken im Array haben werden, da die Socken entfernt werden, sobald sie übereinstimmen.

10
trpt4him

Socken, ob echte oder eine analoge Datenstruktur, würden paarweise geliefert.

Die einfachste Antwort ist, bevor das Paar getrennt werden kann, eine einzelne Datenstruktur für das Paar zu initialisieren, die einen Zeiger auf die linke und rechte Socke enthält, sodass auf Socken direkt oder über ihr Paar verwiesen werden kann. Eine Socke kann auch erweitert werden, um einen Zeiger auf ihren Partner zu enthalten.

Dies löst jedes Paarungsproblem, indem es mit einer Abstraktionsebene entfernt wird.

Die offensichtliche Antwort auf das praktische Problem der Paarung von Socken lautet: Lassen Sie nicht zu, dass Ihre Socken jemals ungepaart sind. Socken werden als Paar geliefert, als Paar in die Schublade gesteckt (möglicherweise durch Zusammenballen) und als Paar getragen. Aber der Punkt, an dem das Entkoppeln möglich ist, liegt in der Waschmaschine. Alles, was benötigt wird, ist ein physikalischer Mechanismus, der es den Socken ermöglicht, zusammen zu bleiben und effizient zu waschen.

Es gibt zwei physikalische Möglichkeiten:

Für ein "Paar" -Objekt, das einen Zeiger auf jede Socke hält, könnten wir eine Stofftasche haben, mit der wir die Socken zusammenhalten. Das scheint ein gewaltiger Aufwand zu sein.

Damit jede Socke einen Bezug zur anderen behält, gibt es eine gute Lösung: einen Druckknopf (oder einen Druckknopf, wenn Sie Amerikaner sind), wie zum Beispiel:

http://www.aliexpress.com/compare/compare-invisible-snap-buttons.html

Alles, was Sie tun müssen, ist, Ihre Socken gleich nach dem Ausziehen und Einlegen in den Wäschekorb zusammenzureißen. Auch hier haben Sie das Problem beseitigt, dass Sie Ihre Socken mit einer physischen Abstraktion des Paarkonzepts koppeln müssen.

10
mozboz

Betrachten Sie eine Hash-Tabelle der Größe 'N'.

Wenn wir von einer Normalverteilung ausgehen, ist die geschätzte Anzahl von "Insertionen", bei denen mindestens eine Socke einem Bucket zugeordnet ist, NlogN (dh alle Bucket sind voll).

Ich hatte dies als Teil eines anderen Puzzles abgeleitet, würde mich aber freuen, wenn ich das Gegenteil beweisen würde. Hier ist mein Blogartikel daz

'N' entspricht einer ungefähren Obergrenze für die Anzahl der eindeutigen Farben/Muster der Socken, die Sie haben.

Wenn Sie eine Kollision haben (a.k.a. ein Match), ziehen Sie einfach dieses Paar Socken aus. Wiederholen Sie das gleiche Experiment mit der nächsten Charge von NlogN-Socken. Das Schöne daran ist, dass Sie aufgrund der Funktionsweise des menschlichen Geistes parallele NlogN-Vergleiche (Kollisionsauflösung) durchführen können. :-)

9
Arvind

Ich habe einfache Schritte unternommen, um meinen Aufwand auf einen Prozess zu reduzieren, der O(1) Zeit in Anspruch nimmt.

Indem ich meine Eingaben auf eine von zwei Arten von Socken reduziere (weiße Socken für die Erholung, schwarze Socken für die Arbeit), muss ich nur feststellen, welche von zwei Socken ich in der Hand habe. (Technisch gesehen habe ich den Prozess auf O(0) Zeit reduziert, da sie nie zusammen gewaschen werden.)

Es sind einige Vorleistungen erforderlich, um die gewünschten Socken zu finden und in ausreichender Menge einzukaufen, damit Ihre vorhandenen Socken nicht mehr benötigt werden. Da ich dies getan hatte, bevor ich schwarze Socken brauchte, war mein Aufwand minimal, aber die Laufleistung kann variieren.

Solch eine Vorleistung wurde schon oft in sehr populärem und effektivem Code gesehen. Beispiele hierfür sind: # DEFINE'ing pi to some decimals (es gibt andere Beispiele, aber das fällt mir gerade ein).

8
Scott Brickey

Ich habe meine Socken gerade fertig gepaart und festgestellt, dass der beste Weg, dies zu tun, der folgende ist:

  • Wähle eine der Socken und lege sie weg (erstelle einen 'Eimer' für dieses Paar)
  • Wenn es sich bei dem nächsten um das Paar des vorherigen handelt, legen Sie es in den vorhandenen Bucket, andernfalls erstellen Sie einen neuen.

Im schlimmsten Fall bedeutet dies, dass Sie n/2 verschiedene Eimer haben und n-2 Bestimmungen darüber haben, welcher Eimer das Paar der aktuellen Socke enthält. Offensichtlich funktioniert dieser Algorithmus gut, wenn Sie nur wenige Paare haben. Ich habe es mit 12 Paaren gemacht.

Es ist nicht so wissenschaftlich, aber es funktioniert gut :)

8
maestro

Meine Lösung entspricht nicht genau Ihren Anforderungen, da formal O(n) "extra" Speicherplatz benötigt wird. In Anbetracht meiner Bedingungen ist es jedoch in meiner praktischen Anwendung sehr effizient. Daher denke ich, dass es interessant sein sollte.

Mit anderer Aufgabe kombinieren

Die besondere Bedingung in meinem Fall ist, dass ich keinen Trockner benutze. Hänge meine Tücher einfach an einen normalen Wäschetrockner. Das Aufhängen von Tüchern erfordert O(n)-Operationen (ich betrachte übrigens immer Behälterverpackung Problem hier) und das Problem erfordert von Natur aus den linearen "zusätzlichen" Raum. Wenn ich eine neue Socke aus dem Eimer nehme, versuche ich, sie neben das Paar zu hängen, wenn das Paar bereits aufgehängt ist. Wenn es eine Socke von einem neuen Paar ist, lasse ich etwas Platz daneben.

Oracle Machine ist besser ;-)

Es erfordert offensichtlich einige zusätzliche Arbeit, um zu überprüfen, ob die passende Socke bereits irgendwo hängt, und es würde eine Lösung O(n^2) mit einem Koeffizienten von 1/2 für einen Computer ergeben. Aber in diesem Fall ist der "menschliche Faktor" tatsächlich ein Vorteil - ich kann die passende Socke normalerweise sehr schnell (fast O(1)) identifizieren, wenn sie bereits aufgehängt war (wahrscheinlich liegt ein unmerkliches In-Brain-Caching vor) - betrachten Sie sie als eine Art von begrenztem "Oracle" wie in Oracle Machine ;-) Wir Menschen haben diese Vorteile in einigen Fällen gegenüber digitalen Maschinen ;-)

Haben Sie es fast O(n)!

Wenn ich also das Problem der Paarung von Socken mit dem Problem des Aufhängens von Kleidungsstücken verbinde, bekomme ich O(n) "zusätzlichen Platz" kostenlos und habe eine Lösung, die ungefähr O(n) in der Zeit ist, nur ein wenig mehr Arbeit erfordert als einfache Aufhängetücher und sofort vollständigen Zugriff ermöglicht Paar Socken auch an einem sehr schlechten Montagmorgen ... ;-)

8
wrzasa

Wenn die "Verschieben" -Operation ziemlich teuer und die "Vergleichen" -Operation billig ist und Sie den gesamten Satz trotzdem in einen Puffer verschieben müssen, in dem die Suche viel schneller ist als im ursprünglichen Speicher ... integrieren Sie einfach die Sortierung in die obligatorische Bewegung.

Ich fand, dass die Integration des Sortierprozesses in das Aufhängen zum Trocknen ein Kinderspiel ist. Ich muss sowieso jede Socke aufheben und aufhängen (bewegen) und es kostet mich nichts, sie an einer bestimmten Stelle an den Saiten aufzuhängen. Jetzt, nur um die Suche nach dem gesamten Puffer (den Strings) nicht zu erzwingen, entscheide ich mich dafür, Socken nach Farbe/Farbton anzuordnen. Links dunkler, rechts heller, vorne bunter usw. Bevor ich jetzt jede Socke aufhänge, schaue ich in die "richtige Umgebung", ob es bereits eine passende gibt - dies "scannt" auf 2-3 andere Socken - und wenn ja Ich hänge den anderen direkt daneben. Dann rolle ich sie paarweise, während ich sie von den Saiten entferne, wenn sie trocken sind.

Dies unterscheidet sich vielleicht nicht allzu sehr von der Frage nach der "Stapelbildung nach Farbe", die in den häufigsten Antworten vorgeschlagen wird. Zunächst kann ich jedoch problemlos feststellen, ob "lila" zu "rot" oder "blau" wechselt. es geht einfach dazwischen. Durch die Integration von zwei Vorgängen (zum Trocknen und Sortieren aufhängen) entspricht der Aufwand für das Sortieren beim Aufhängen etwa 10% des Aufwandes für das separate Sortieren.

8
SF.

Ich hoffe, ich kann etwas Neues zu diesem Problem beitragen. Mir ist aufgefallen, dass alle Antworten die Tatsache vernachlässigen, dass es zwei Punkte gibt, an denen Sie Vorverarbeitung ausführen können, ohne die Gesamtleistung Ihrer Wäsche zu beeinträchtigen.

Wir müssen auch bei großen Familien nicht von einer großen Anzahl von Socken ausgehen. Socken werden aus der Schublade genommen und getragen, und dann werden sie an einen Ort (vielleicht einen Mülleimer) geworfen, an dem sie bleiben, bevor sie gewaschen werden. Ich würde said bin zwar nicht als LIFO-Stack bezeichnen, aber davon kann man ausgehen

  1. die Leute werfen ihre beiden Socken ungefähr im selben Bereich des Mülls weg,
  2. die Bin wird zu keinem Zeitpunkt randomisiert, und daher
  3. jede Teilmenge, die von oben aus diesem Behälter entnommen wird, enthält im Allgemeinen beide Socken eines Paares.

Da alle mir bekannten Waschmaschinen eine begrenzte Größe haben (unabhängig davon, wie viele Socken Sie waschen müssen) und die eigentliche Zufallsauswahl in der Waschmaschine erfolgt, haben wir immer kleine Teilmengen, die fast keine enthalten, unabhängig davon, wie viele Socken wir haben Singletons.

Unsere beiden Vorverarbeitungsschritte sind "Socken auf die Wäscheleine legen" und "Socken von der Wäscheleine nehmen", was wir tun müssen, um Socken zu erhalten, die nicht nur sauber, sondern auch trocken sind. Wie bei Waschmaschinen sind Wäscheleinen endlich, und ich gehe davon aus, dass wir den gesamten Teil der Linie haben, in dem wir unsere Socken in Sicht bringen.

Hier ist der Algorithmus für put_socks_on_line ():

while (socks left in basket) {
 take_sock();
 if (cluster of similar socks is present) { 
   Add sock to cluster (if possible, next to the matching pair)
 } else {
  Hang it somewhere on the line, this is now a new cluster of similar-looking socks.      
  Leave enough space around this sock to add other socks later on 
 }
}

Verschwenden Sie nicht Ihre Zeit damit, die Socken zu bewegen oder nach dem besten Match zu suchen. Dies sollte alles in O (n) geschehen, was wir auch brauchen würden, um sie unsortiert in die Reihe zu bringen. Die Socken sind noch nicht gepaart, wir haben nur einige Ähnlichkeitscluster auf der Linie. Es ist hilfreich, dass wir hier nur eine begrenzte Anzahl von Socken haben, da dies uns hilft, "gute" Cluster zu erstellen (zum Beispiel, wenn die Socken nur schwarze Socken enthalten, ist das Gruppieren nach Farben nicht der richtige Weg).

Hier ist der Algorithmus für take_socks_from_line ():

while(socks left on line) {
 take_next_sock();
 if (matching pair visible on line or in basket) {
   Take it as well, pair 'em and put 'em away
 } else {
   put the sock in the basket
 }

Ich möchte darauf hinweisen, dass es zur Verbesserung der Geschwindigkeit der verbleibenden Schritte ratsam ist, nicht nach dem Zufallsprinzip die nächste Socke auszuwählen, sondern nacheinander Socke für Socke aus jedem Cluster zu ziehen. Beide Vorverarbeitungsschritte nehmen nicht mehr Zeit in Anspruch, als nur die Socken auf die Linie oder in den Korb zu legen, was wir auf jeden Fall tun müssen, daher sollte dies die Wäscheleistung erheblich verbessern.

Danach ist es einfach, den Hash-Partitionierungsalgorithmus auszuführen. Normalerweise sind ungefähr 75% der Socken bereits gepaart, so dass ich eine sehr kleine Untergruppe von Socken habe, und diese Untergruppe ist bereits (etwas) gruppiert (ich füge nach den Vorverarbeitungsschritten nicht viel Entropie in meinen Korb ein). Eine andere Sache ist, dass die verbleibenden Cluster in der Regel klein genug sind, um sofort gehandhabt zu werden, sodass es möglich ist, einen ganzen Cluster aus dem Korb zu nehmen.

Hier ist der Algorithmus für sort_remaining_clusters ():

while(clusters present in basket) {
  Take out the cluster and spread it
  Process it immediately
  Leave remaining socks where they are
}

Danach sind nur noch wenige Socken übrig. Hier füge ich zuvor ungepaarte Socken in das System ein und verarbeite die verbleibenden Socken ohne speziellen Algorithmus - die verbleibenden Socken sind sehr wenige und können sehr schnell visuell verarbeitet werden.

Für alle verbleibenden Socken gehe ich davon aus, dass ihre Gegenstücke noch ungewaschen sind, und lege sie für die nächste Iteration weg. Wenn Sie mit der Zeit ein Wachstum von ungepaarten Socken feststellen (ein "Sockenleck"), sollten Sie Ihren Papierkorb überprüfen - er könnte zufällig ausgewählt werden (haben Sie Katzen, die dort schlafen?)

Ich weiß, dass diese Algorithmen eine Menge Annahmen treffen: einen Behälter, der als eine Art LIFO Stapel fungiert, eine begrenzte, normale Waschmaschine und eine begrenzte, normale Wäscheleine - aber dies funktioniert immer noch mit einer sehr großen Anzahl von Socken .

Parallelität: Solange Sie beide Socken in den gleichen Behälter werfen, können Sie alle diese Schritte problemlos parallelisieren.

8
Philipp Flenker

Was ist mit einer Vorverarbeitung? Ich würde eine Marke oder ID-Nummer in jede Socke so nähen, dass jedes Paar dieselbe Marke/ID-Nummer hat. Dieser Vorgang kann jedes Mal durchgeführt werden, wenn Sie ein neues Paar Socken kaufen. Dann könnten Sie eine Radix-Sortierung ausführen, um O(n) Gesamtkosten zu erhalten. Suchen Sie einen Platz für jede Marke/ID-Nummer und wählen Sie einfach alle Socken nacheinander aus und platzieren Sie sie an der richtigen Stelle.

7
elvitucho

Erstellen Sie eine Hash-Tabelle, die für unvergleichliche Socken verwendet wird. Verwenden Sie dabei das Muster als Hash. Iteriere nacheinander über die Socken. Wenn die Socke eine Musterübereinstimmung in der Hash-Tabelle hat, nehmen Sie die Socke aus der Tabelle und bilden Sie ein Paar. Wenn die Socke keine Übereinstimmung hat, legen Sie sie in den Tisch.

7
viper110110

Das Problem der Sortierung Ihre n Paar Socken ist O (n). Bevor Sie sie in die Wäsche werfen Korb, fädeln Sie die linke zur rechten. Beim Herausnehmen schneiden Sie den Faden ab und legen jedes Paar in Ihre Schublade - 2 Operationen mit n Paaren, also O (n).

Nun ist die nächste Frage einfach, ob Sie Ihre eigene Wäsche machen und Ihre Frau ihre. Das ist wahrscheinlich ein Problem in einem völlig anderen Bereich von Problemen. :)

7
Fred Mitchell

Ich habe während meiner Promotion (in Informatik) sehr oft darüber nachgedacht. Ich habe mehrere Lösungen gefunden, abhängig von der Fähigkeit, Socken zu unterscheiden und so schnell wie möglich die richtigen Paare zu finden.

Angenommen, die Kosten für das Betrachten von Socken und das Auswendiglernen ihrer charakteristischen Muster ist vernachlässigbar (ε). Dann ist die beste Lösung, einfach alle Socken auf einen Tisch zu werfen. Dies beinhaltet die folgenden Schritte:

  1. Wirf alle Socken auf einen Tisch (1) und erstelle eine Hashmap {pattern: position} (ε)
  2. Während noch Socken übrig sind (n/2):
    1. Nimm eine zufällige Socke (1)
    2. Finden Sie die Position der entsprechenden Socke (ε)
    3. Nimm die Socke (1) und bewahre das Paar auf

Dies ist in der Tat die schnellste Möglichkeit und wird in n + 1 = O(n) Komplexität ausgeführt. Es wird jedoch davon ausgegangen, dass Sie sich perfekt an alle Muster erinnern. In der Praxis ist dies nicht der Fall, und meiner persönlichen Erfahrung nach finden Sie das passende Paar manchmal nicht auf Anhieb:

  1. Wirf alle Socken auf einen Tisch (1)
  2. Während noch Socken übrig sind (n/2):
    1. Nimm eine zufällige Socke (1)
    2. solange es nicht gepaart ist (1/P):
      1. Finden Sie eine Socke mit einem ähnlichen Muster
      2. Nimm die Socke und vergleiche beide (1)
      3. Wenn in Ordnung, speichern Sie Paar

Dies hängt nun von unserer Fähigkeit ab, passende Paare zu finden. Dies gilt insbesondere, wenn Sie dunkelgraue Paare oder weiße Sportsocken haben, die oft sehr ähnliche Muster aufweisen! Angenommen, Sie haben die Wahrscheinlichkeit, dass P die entsprechende Socke findet. Sie benötigen im Durchschnitt 1/P-Versuche, bevor Sie die entsprechende Socke finden, um ein Paar zu bilden. Die Gesamtkomplexität beträgt 1 + (n/2) * (1 + 1/P) = O (n).

Beide sind linear in der Anzahl der Socken und sind sehr ähnliche Lösungen. Lassen Sie uns das Problem leicht modifizieren und zugeben, dass Sie mehrere Paare von ähnlichen Socken im Set haben und dass es einfach ist, mehrere Paare von Socken in einem Zug aufzubewahren (1 + ε ). Für K verschiedene Muster können Sie implementieren:

  1. Für jede Socke (n):
    1. Nimm eine zufällige Socke (1)
    2. Legen Sie es auf den Cluster seines Musters
  2. Für jeden Cluster (K):
    1. Nimm Cluster und bewahre ein Paar Socken auf (1 + ε)

Die Gesamtkomplexität wird zu n + K = O (n). Es ist immer noch linear, aber die Auswahl des richtigen Algorithmus kann jetzt stark von den Werten von P und K abhängen! Es kann jedoch erneut beanstandet werden, dass Sie möglicherweise Schwierigkeiten haben, Cluster für jede Socke zu finden (oder zu erstellen).

Außerdem können Sie auch Zeit verlieren, indem Sie auf Websites nach dem besten Algorithmus suchen und Ihre eigene Lösung vorschlagen :)

5
eldams

Auf dem Weg zu einem effizienten Algorithmus zum Koppeln von Socken von einem Stapel

Voraussetzungen

  1. Es muss mindestens eine Socke im Stapel sein
  2. Der Tisch muss groß genug sein, um N/2 Socken (Worst Case) aufzunehmen, wobei N die Gesamtzahl der Socken ist.

Algorithmus

Versuchen:

  1. Nimm die erste Socke
  2. Leg es auf den Tisch
  3. Nimm die nächste Socke und sieh sie dir an.
  4. Jetzt scannen Sie die Socken auf dem Tisch (wirft Ausnahme, wenn keine Socken mehr auf dem Tisch sind)
  5. Gibt es eine Übereinstimmung? a) ja => entferne die passende Socke aus dem Tisch b) nein => lege die Socke auf den Tisch (kann die Ausnahme "der Tisch ist nicht groß genug" werfen)

Außer:

  • Der Tisch ist nicht groß genug:
    Mischen Sie alle ungepaarten Socken sorgfältig zusammen und nehmen Sie dann den Betrieb wieder auf
    // Diese Operation führt zu einem neuen Stapel und einer leeren Tabelle

  • Keine Socken mehr auf dem Tisch:
    Werfen (die letzte ungepaarte Socke)

  • Keine Socken mehr auf dem Stapel:
    Waschküche verlassen

Endlich:

  • Wenn noch Socken im Stapel sind:
    Gehe zu 3

Bekannte Probleme

Der Algorithmus tritt in eine Endlosschleife ein, wenn kein Tisch vorhanden ist oder nicht genügend Platz für mindestens einen Strumpf auf dem Tisch vorhanden ist.

Mögliche Verbesserung

Abhängig von der Anzahl der zu sortierenden Socken kann der Durchsatz erhöht werden, indem die Socken auf dem Tisch sortiert werden , sofern genügend Platz vorhanden ist.

Damit dies funktioniert, ist ein Attribut erforderlich, das für jedes Paar Socken einen eindeutigen Wert hat. Ein solches Attribut kann leicht aus den visuellen Eigenschaften der Socken synthetisiert werden.

Sortieren Sie die Socken auf dem Tisch nach diesem Attribut. Nennen wir dieses Attribut "Farbe". Ordnen Sie die Socken in einer Reihe an, und setzen Sie rechts dunklere Socken (d. H. Push_back ()) und links hellere Socken (d. Push_front ()).

Bei großen Haufen und insbesondere bei bisher nicht sichtbaren Socken kann die Attributsynthese viel Zeit in Anspruch nehmen, sodass der Durchsatz anscheinend abnimmt. Diese Attribute können jedoch im Speicher beibehalten und wiederverwendet werden.

Es sind einige Untersuchungen erforderlich, um die Effizienz dieser möglichen Verbesserung zu bewerten. Folgende Fragen stellen sich:

  • Was ist die optimale Anzahl an Socken, die mit der obigen Verbesserung gepaart werden können?
  • Wie viele Iterationen sind für eine bestimmte Anzahl von Socken erforderlich, bevor der Durchsatz steigt?
    a) für die letzte Iteration
    b) für alle Iterationen insgesamt

PoC gemäß den MCVE Richtlinien:

#include <iostream>
#include <vector>
#include <string>
#include <time.h>

using namespace std;

struct pileOfsocks {
    pileOfsocks(int pairCount = 42) :
        elemCount(pairCount<<1) {
        srand(time(NULL));
        socks.resize(elemCount);

        vector<int> used_colors;
        vector<int> used_indices;

        auto getOne = [](vector<int>& v, int c) {
            int r;
            do {
                r = Rand() % c;
            } while (find(v.begin(), v.end(), r) != v.end());
            v.Push_back(r);
            return r;
        };

        for (auto i = 0; i < pairCount; i++) {
            auto sock_color = getOne(used_colors, INT_MAX);
            socks[getOne(used_indices, elemCount)] = sock_color;
            socks[getOne(used_indices, elemCount)] = sock_color;
        }
    }

    void show(const string& Prompt) {
        cout << Prompt << ":" << endl;
        for (auto i = 0; i < socks.size(); i++){
            cout << socks[i] << " ";
        }
        cout << endl;
    }

    void pair() {
        for (auto i = 0; i < socks.size(); i++) {
            std::vector<int>::iterator it = find(unpaired_socks.begin(), unpaired_socks.end(), socks[i]);
            if (it != unpaired_socks.end()) {
                unpaired_socks.erase(it);
                paired_socks.Push_back(socks[i]);
                paired_socks.Push_back(socks[i]);
            }
            else
                unpaired_socks.Push_back(socks[i]);
        }

        socks = paired_socks;
        paired_socks.clear();
    }

private:
    int elemCount;
    vector<int> socks;
    vector<int> unpaired_socks;
    vector<int> paired_socks;
};

int main() {
    pileOfsocks socks;

    socks.show("unpaired socks");
    socks.pair();
    socks.show("paired socks");

    system("pause");
    return 0;
}
2
Laszlo

Scherzmodus ein

Es tut mir leid, das zu sagen, aber Sie alle liegen eindeutig falsch. Für Ihren realen Anwendungsfall können Sie mit Socken mühelos und in O (1) eine perfekte Sockenübereinstimmung erzielen.

Kaufen Sie einfach eine Tüte diese , befestigen Sie Ihre Socken jeden Tag, wenn Sie sie aus Ihren Füßen ziehen und wenn sie aus der Waschmaschine kommen, sind sie magisch schon gepaart.

(Ich bin in keiner Weise mit diesem Verkäufer verbunden, Sie können dieses Zeug von vielen Orten finden)

Scherzmodus aus

1
singe3

Zwei Denkansätze: Die Geschwindigkeit, mit der eine Übereinstimmung gefunden wird, im Vergleich zur Geschwindigkeit, mit der alle Übereinstimmungen gefunden werden, im Vergleich zum Speicher.

Für den zweiten Fall wollte ich auf eine GPU-parallele Version hinweisen, die die Socken für alle Übereinstimmungen abfragt.

Wenn Sie mehrere Eigenschaften haben, für die eine Übereinstimmung erzielt werden soll, können Sie gruppierte Tupel und schickere Zip-Iteratoren sowie die Transformationsfunktionen von thrust verwenden. Der Einfachheit halber wird hier eine einfache GPU-basierte Abfrage aufgeführt:

//test.cu
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/copy.h>
#include <thrust/count.h>
#include <thrust/remove.h>
#include <thrust/random.h>
#include <iostream>
#include <iterator>
#include <string>

// Define some types for pseudo code readability
typedef thrust::device_vector<int> GpuList;
typedef GpuList::iterator          GpuListIterator;

template <typename T>
struct ColoredSockQuery : public thrust::unary_function<T,bool>
{
    ColoredSockQuery( int colorToSearch )
    { SockColor = colorToSearch; }

    int SockColor;

    __Host__ __device__
    bool operator()(T x)
    {
        return x == SockColor;
    }
};


struct GenerateRandomSockColor
{
    float lowBounds, highBounds;

    __Host__ __device__
    GenerateRandomSockColor(int _a= 0, int _b= 1) : lowBounds(_a), highBounds(_b) {};

    __Host__ __device__
    int operator()(const unsigned int n) const
    {
        thrust::default_random_engine rng;
        thrust::uniform_real_distribution<float> dist(lowBounds, highBounds);
        rng.discard(n);
        return dist(rng);
    }
};

template <typename GpuListIterator>
void PrintSocks(const std::string& name, GpuListIterator first, GpuListIterator last)
{
    typedef typename std::iterator_traits<GpuListIterator>::value_type T;

    std::cout << name << ": ";
    thrust::copy(first, last, std::ostream_iterator<T>(std::cout, " "));
    std::cout << "\n";
}

int main()
{
    int numberOfSocks = 10000000;
    GpuList socks(numberOfSocks);
    thrust::transform(thrust::make_counting_iterator(0),
                      thrust::make_counting_iterator(numberOfSocks),
                      socks.begin(),
                      GenerateRandomSockColor(0, 200));

    clock_t start = clock();

    GpuList sortedSocks(socks.size());
    GpuListIterator lastSortedSock = thrust::copy_if(socks.begin(),
                                                     socks.end(),
                                                     sortedSocks.begin(),
                                                     ColoredSockQuery<int>(2));
    clock_t stop = clock();

    PrintSocks("Sorted Socks: ", sortedSocks.begin(), lastSortedSock);

    double elapsed = (double)(stop - start) * 1000.0 / CLOCKS_PER_SEC;
    std::cout << "Time elapsed in ms: " << elapsed << "\n";

    return 0;
}

    //nvcc -std=c++11 -o test test.cu

Laufzeit für 10 Millionen Socken: 9 ms

1
JMan Mousey

Meine vorgeschlagene Lösung geht davon aus, dass alle Socken im Detail identisch sind, mit Ausnahme von Farbe. Wenn es mehr Details gibt, die zwischen Socken verschoben werden müssen, können diese Details verwendet werden, um in meinem Beispiel verschiedene Arten von Socken anstelle von Farben zu definieren.

Wenn wir einen Haufen Socken haben, kann eine Socke in drei Farben erhältlich sein: Blau, Rot oder Grün.

Dann können wir für jede Farbe einen parallelen Arbeiter erstellen; es hat eine eigene Liste, um entsprechende Farben zu füllen.

At time i:

Blue  read  Pile[i]    : If Blue  then Blue.Count++  ; B=TRUE  ; sync

Red   read  Pile[i+1]  : If Red   then Red.Count++   ; R=TRUE  ; sync

Green read  Pile [i+2] : If Green then Green.Count++ ; G=TRUE  ; sync

Mit Synchronisationsprozess:

Sync i:

i++

If R is TRUE:
    i++
    If G is TRUE:
        i++

Dies erfordert eine Initialisierung:

Init:

If Pile[0] != Blue:
    If      Pile[0] = Red   : Red.Count++
    Else if Pile[0] = Green : Green.Count++

If Pile[1] != Red:
    If Pile[0] = Green : Green.Count++

Wo

Best Case: B, R, G, B, R, G, .., B, R, G

Worst Case: B, B, B, .., B

Time(Worst-Case) = C * n ~ O(n)

Time(Best-Case) = C * (n/k) ~ O(n/k)

n: number of sock pairs
k: number of colors
C: sync overhead
1
Khaled.K