Die Aufgabe
- Sie erhalten eine veränderbare Zeichenfolge, die übereinstimmt
[a-z]+( [a-z]+)*
. - Sie müssen es in die Zeichenfolge umwandeln, die die gleichen Wörter enthält, jedoch in umgekehrter Reihenfolge, so dass "Hallo, da sind alle" zu "Hallo, da sind alle" wird.
- Sie dürfen nicht mehr als eine konstante Menge zusätzlichen Speichers verwenden (also nicht die gesamte Zeichenfolge oder ein ganzes Wort in einen Puffer kopieren, den Sie gerade zugewiesen haben).
- Es gibt keine zeitlichen Einschränkungen. Hoffnungslos ineffizient zu sein, schadet Ihrer Punktzahl nicht.
- Wenn Ihre Sprache die Mutation von Zeichenfolgen nicht zulässt, sind Arrays von Zeichen ein akzeptabler Ersatz.
Ihre Punktzahl
- Ihre Punktzahl wird nur anhand der Anzahl der Zuordnungen gezählt, die Sie zu Zeichenfolgenelementen vornehmen (kleine Punktzahlen sind am besten). Wenn Sie eine Bibliotheksfunktion verwenden, die in die Zeichenfolge schreibt, zählen auch deren Schreibvorgänge.
- Angenommen, die Anzahl der Zuweisungen, die Sie für die Eingabe von s benötigen, ist n (s) . Dann ist Ihre Punktzahl das Maximum (pedantisch, supremum) über alle Eingaben s (passend zur oben angegebenen Regex) von n (s) / Länge (n) . Wenn Sie dies nicht genau berechnen können, können Sie die niedrigste Obergrenze verwenden, die Sie nachweisen können.
- Sie können einen Gleichstand beenden, wenn Sie nachweisen können, dass Ihr Algorithmus asymptotisch weniger Zuweisungen verwendet (dies kann auch bei gleichem Ergebnis der Fall sein, siehe unten). Wenn Sie dies nicht tun können, können Sie ein Band durchbrechen, indem Sie zeigen, dass Sie weniger zusätzlichen Speicher verwenden. Die erste Unterbrechungsbedingung hat jedoch immer Vorrang.
- Bei einigen Eingaben muss sich jedes Zeichen ändern, daher ist es nicht möglich, weniger als 1 zu erzielen.
- Ich kann mir einen einfachen Algorithmus mit Punktzahl 2 vorstellen (aber ich gebe ihn nicht ein).
Hinweise zu Suprema und Krawatten
- Ein Supremum einer Reihe von Zahlen ist die kleinste Zahl, die nicht kleiner als eine von ihnen ist. Dies entspricht in etwa dem Maximum einer Menge, mit der Ausnahme, dass einige unendliche Mengen wie {2/3, 3/4, 4/5, 5/6, ...} kein einzelnes maximales Element haben, aber immer noch ein Supremum haben. in diesem Fall 1.
- Wenn es Ihnen gelingt, nur eine konstante Anzahl von Zuweisungen über meinen Algorithmus mit Punktzahl 2 (z. B.) zu "speichern", beträgt Ihre Punktzahl immer noch 2, da Sie mit zunehmender Eingabe beliebig nahe an 2 kommen. Allerdings gewinnt man im Tie-Break, wenn es dazu kommt.
code-challenge
Ben Millwood
quelle
quelle
little-omega(1)
Raum nur, indem es auf den Stapel gelegt wird.O(1)
zusätzlichem Platz durchzuführen . Sie benötigenO(log n)
Platz zum Speichern einer Indexposition, da eine k-Bit-Ganzzahl nur Zeichenfolgen mit einer Länge von bis zu darin speichern kann2^k
. Das Begrenzen der Länge der Zeichenketten macht die Herausforderung ziemlich sinnlos, da jeder Algorithmus aufO(1)
diese Weise Platz beanspruchen würde .Antworten:
Python, Score:
21,51,25Dies ist die direkte Kombination zwischen der Antwort von primo und meiner Antwort. Also auch ihm zu verdanken!
Der Beweis ist noch in Bearbeitung, aber hier ist der Code zum Spielen! Wenn Sie ein Gegenbeispiel für eine Punktzahl größer als 1,25 finden (oder wenn es einen Fehler gibt), lassen Sie es mich wissen!
Derzeit ist der schlimmste Fall:
Dabei gibt es genau n der Buchstaben "a", "b", "c" und "" (Leerzeichen) und genau zwei "d". Die Länge der Zeichenfolge beträgt 4n + 2 und die Anzahl der Zuweisungen beträgt 5n + 2 , was eine Punktzahl von 5/4 = 1,25 ergibt .
Der Algorithmus arbeitet in zwei Schritten:
k
solchestring[k]
undstring[n-1-k]
sind Wortgrenzenstring[:k]+string[n-1-k:]
(dh Verkettung der erstenk
und letztenk
Zeichen).Wo
n
ist die Länge der Zeichenfolge.Die Verbesserung, die dieser Algorithmus bietet, ergibt sich aus der "kleinen Änderung" in Schritt 2. Es ist im Grunde das Wissen, dass in der verketteten Zeichenfolge die Zeichen an der Position
k
undk+1
Wortgrenzen sind (dh sie sind Leerzeichen oder das erste / letzte Zeichen in einem Wort). und so können wir die Zeichen in Positionk
undk+1
mit dem entsprechenden Zeichen in der letzten Zeichenfolge direkt ersetzen und einige Zuweisungen speichern. Dies entfernt den ungünstigsten Fall aus dem Host-WortumkehralgorithmusEs gibt Fälle, in denen wir solche nicht finden
k
können. In diesem Fall führen wir einfach den "Any Word Reversal Algorithmus" für die gesamte Zeichenfolge aus.Der Code ist lang, um diese vier Fälle beim Ausführen des Wortumkehralgorithmus für die "verkettete" Zeichenfolge zu behandeln:
k
wird nicht gefunden (f_long = -2
)string[k] != ' ' and string[n-1-k] != ' '
(f_long = 0
)string[k] != ' ' and string[n-1-k] == ' '
(f_long = 1
)string[k] == ' ' and string[n-1-k] != ' '
(f_long = -1
)Ich bin sicher, dass der Code gekürzt werden kann. Momentan ist es lange her, weil ich am Anfang kein klares Bild des gesamten Algorithmus hatte. Ich bin sicher, man kann es so gestalten, dass es in einem kürzeren Code dargestellt wird =)
Probelauf (der erste ist meiner, der zweite ist der Primo):
Sie können sehen, dass die Punktzahl fast gleich ist, mit Ausnahme des schlechtesten Falls des Host-Wortumkehralgorithmus im dritten Beispiel, für den mein Ansatz eine Punktzahl von weniger als 1,25 ergibt
Python, Score: 1,5
Die genaue Anzahl der Zuordnungen kann durch die Formel angenähert werden:
mit dem schlimmsten Fall ist:
mit 55 Aufgaben an einer Saite mit der Länge 37.
Die Idee ähnelt meiner vorherigen, es ist nur so, dass ich in dieser Version versucht habe, Präfix und Suffix an Wortgrenzen mit einem Längenunterschied von höchstens 1 zu finden. Dann führe ich meinen vorherigen Algorithmus mit diesem Präfix und Suffix aus (stelle sie mir als verkettet vor). . Fahren Sie dann mit dem unbearbeiteten Teil fort.
Zum Beispiel für den vorigen schlimmsten Fall:
Wir werden zuerst das Wort "ab" und "c" (4 Zuordnungen) umkehren, um zu sein:
Wir wissen, dass es sich an der Grenze früher um Leerzeichen handelte (es gibt viele Fälle, die behandelt werden müssen, aber Sie können dies tun), sodass wir das Leerzeichen an der Grenze nicht codieren müssen. Dies ist die Hauptverbesserung gegenüber dem vorherigen Algorithmus .
Dann laufen wir endlich auf die mittleren vier Zeichen, um zu bekommen:
Insgesamt 8 Zuordnungen, die für diesen Fall optimal sind, da sich alle 8 Zeichen geändert haben.
Dies beseitigt den schlechtesten Fall im vorherigen Algorithmus, da der schlechteste Fall im vorherigen Algorithmus beseitigt ist.
Sehen Sie sich einen Probelauf an (und vergleichen Sie ihn mit @primos Antwort - dies ist die zweite Zeile):
Die Antwort von primo ist im Allgemeinen besser, obwohl ich in einigen Fällen 1 Punkt Vorteil haben kann =)
Auch sein Code ist viel kürzer als meiner, haha.
Python, Score: asymptotisch 2, im Normalfall viel weniger
alter Code aus Platzgründen entfernt
Die Idee ist , zu durchlaufen jeden Index, und für jeden Index
i
, wir den Charakter nehmen, berechnen die neue Positionj
, merken an Position den Charakterj
, weisen das Zeichen ani
zuj
, und wiederholen Sie mit Charakter am Indexj
. Da wir die Leerzeicheninformationen benötigen, um die neue Position zu berechnen, codiere ich das alte Leerzeichen als Großbuchstaben des neuen Buchstabens und das neue Leerzeichen als '@'.quelle
length(string)/3
schlimmsten Fall auf die Länge der Zeichenfolge reduzieren können (z. B. indem Sie jedes Wort im schlimmsten Fall zwingen, mindestens die Länge 2 zu haben), ist die Punktzahl geringer als 2 (im obigen Beispiel ist es 1,67)if any(process_loop(...) for j in range(...))
Müssten die Zuordnungen aus diesen Prozessschleifen nicht gezählt werden?dry_run
Parameter auf einen Wert ungleich Null gesetzt (der Wert aufi
). Innerhalb derprocess_loop
, wenndry_run
nicht Null ist, wird es jede Zuordnung nicht.Perl, Score 1.3̅
Für jedes Nicht-Leerzeichen wird eine Zuweisung ausgeführt und für jedes Leerzeichen zwei Zuweisungen.
Da Leerzeichen nicht mehr als die Hälfte der Gesamtzahl der Zeichen betragen dürfen, beträgt die schlechteste Punktzahl 1,5 .Der Algorithmus hat sich nicht geändert, aber ich kann eine untere Obergrenze nachweisen. Lassen Sie uns zwei Beobachtungen machen:
Es ist dann zu sehen, dass der theoretische 'worst case' mit asymptotisch 1/2 Leerzeichen überhaupt nicht worst case ist:
ab c d e f g h i ...
In der Tat ist es ein ziemlich guter Fall.
Um die obigen Beobachtungen eins und zwei zu vermeiden, müsste jedes Wort mit einem Zeichen in die Mitte eines drei oder mehr Zeichen langen Wortes verschoben werden. Dies würde den schlimmsten Fall nahe legen, der asymptotisch 1/3 Leerzeichen enthält:
a bcd a bcd a ... bc
Oder gleichbedeutend nur zweistellige Wörter:
a bc de fg hi jk ...
Da der schlechteste Fall asymptotisch 1/3 Leerzeichen enthält, wird der schlechteste Fall bewertet beträgt 1,3̅ .
Bearbeiten: Es wurden ein Swap-Zähler und das Verhältnis hinzugefügt.
Die Eingabe erfolgt aus stdin. Beispielnutzung:
Methode
Zu Beginn wird das erste Zeichen der Zeichenfolge an das endgültige Ziel verschoben. Das gerade ersetzte Zeichen wird dann an sein Ziel usw. verschoben. Dies wird fortgesetzt, bis eine der beiden Bedingungen erfüllt ist:
In diesem Fall ist das Zeichen nicht mit dem Leerzeichen vertauscht, sondern in die Spiegelposition des Leerzeichens. Der Algorithmus fährt von dieser Position fort.
Wenn das Ziel zur anfänglichen Startposition des aktuellen Zyklus zurückkehrt, muss das nächste nicht vertauschte Zeichen (oder vielmehr jedes nicht vertauschte Zeichen) gefunden werden. Um dies unter konstanten Speicherbeschränkungen zu tun, werden alle bis zu diesem Zeitpunkt vorgenommenen Auslagerungen zurückverfolgt.
Nach dieser Phase wurde jedes Nicht-Leerzeichen höchstens einmal verschoben. Zum Abschluss werden alle Leerzeichen mit den Zeichen an ihren Spiegelpositionen vertauscht, was zwei Zuweisungsoperationen pro Leerzeichen erfordert.
quelle
Ruby, Punktzahl 2
Als Starter ein sehr grundlegender Algorithmus. Es kehrt zuerst die gesamte Zeichenfolge um und kehrt dann jedes Wort in der Zeichenfolge erneut um. Im schlimmsten Fall (ein Wort, gerade Anzahl von Zeichen) wird die Punktzahl 2.
Verwendung:
quelle
C ++: Score 2
quelle
Rebol
Ich bin mir nicht sicher, wie es ausgeht. In diesem Code gibt es keine direkte Zeichenfolgenzuweisung. Alles wird von dem einen erledigt
reverse/part
erledigt, der an Ort und Stelle innerhalb der Saite und zunächst insgesamt die Saite umkehrt.Einige Details zum Code:
Durchlaufe string (
series
) bis zumtail?
Das erste Mal in der Schleife mache die vollständige Umkehrung des Strings -
reverse/part series tail series
(das ist dasselbe wiereverse series
)Kehren Sie dann jedes Wort um, das Sie bei weiteren Iterationen gefunden haben -
reverse/part series find series space
Sobald ein erschöpftes Wort gefunden wurde, kehre zurück,
tail series
damit es das letzte Wort in der Zeichenfolge umkehrt.reverse/part series tail series
Mit Rebol kann ein String über einen internen Zeiger durchlaufen werden . Sie können dies sehen bei
series: next f
(Zeiger nach Leerzeichen bewegen, so Beginn des nächsten Wortes) undseries: head series
(Zeiger auf den Kopf zurücksetzen).Siehe SerieWeitere Informationen finden .
Anwendungsbeispiel in der Rebol-Konsole:
quelle
C: Punktzahl 2
Dadurch wird die gesamte Zeichenfolge nur einmal umgedreht und dann jedes Wort umgekehrt.
quelle
Python: Punktzahl 2
Fast identisch mit Howards Algorithmus, jedoch werden die Umkehrschritte in umgekehrter Reihenfolge ausgeführt (zuerst werden Wörter umgedreht, dann wird die gesamte Zeichenfolge umgedreht). Zusätzlicher Speicher 3 verwendet wird Byte-Größe Variablen:
i
,j
, undt
. Technischfind
undlen
mit einigen internen Variablen, aber sie könnten genauso einfach wiederverwendet werdeni
oderj
ohne Funktionsverlust.Schnelle Bearbeitung: Speichern von Zeichenfolgen, indem nur bei unterschiedlichen Zeichen getauscht wird, damit ich einige zusätzliche Punkte aus Note 2 herausholen kann.
quelle
Stapel
Ich gebe zu, dass ich die Wertung nicht ganz verstehe (ich glaube, es sind zwei). Aber ich werde sagen - es macht das Ding .
Die Eingabe wird als erster Standardeingabewert genommen, und so Bedürfnisse von Anführungszeichen umgeben sein -
Aufruf:
script.bat "hello there everyone"
out:
everyone there hello
.Vielleicht kann mich jemand anderes bewerten (vorausgesetzt, ich habe mich nicht auf andere Weise disqualifiziert).
quelle
Javascript
Verwendung:
Ich habe das komische Gefühl, etwas verpasst zu haben ...
quelle