Heim >Web-Frontend >js-Tutorial >Festplattenfragmente
Die Phasen, wie ich sie sehe, im Einzelnen:
Nichts davon fühlt sich besonders schwierig an.
Und einiges davon scheint tatsächlich eine weitere lustige algorithmische Herausforderung zu sein!
Ich möchte das ändern:
12345
Dazu:
0..111....22222
Ich muss Folgendes berücksichtigen:
Hier ist mein Festplatten-Generierungsalgorithmus:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
Funktioniert wie ein Zauber!
Was dies einfacher machen würde, wäre eine Liste aller leeren Stellen auf der Festplatte.
Ich muss meinen Algorithmus an zwei Stellen aktualisieren:
Ein Test am Beispiel zeigt die erwarteten Indexzahlen von jedem .!
Dies ist die Liste, die ich durchlaufen werde, während ich Werte vom Ende der Liste zum Anfang und weiter verschiebe.
Aber warte.
Das könnte schwieriger sein, als ich dachte.
Woher weiß ich, wann ich aufhören muss, Werte zu verschieben?
Dies ist der letzte Zustand des kurzen Beispiels:
022111222......
Und zum ersten Beispiel:
0099811188827773336446555566..............
Das bedeutet, dass es einen Punkt gibt, an dem sich alle Ausweise auf der linken und alle Leerzeichen auf der rechten Seite befinden.
Wie würde ich diesen Status überprüfen?
Geben Sie ein: die Zahl 10.
Die Anzahl der zusammenhängenden Leerräume wird niemals höher als 9 sein.
Wenn ich also auf einen leeren Bereich stoße, schaue ich 9 Bereiche nach vorne (oder bis zum Ende der Festplattenliste) und sehe alle leeren Bereiche, dann weiß ich, dass ich mit der Fragmentierung fertig bin.
Ich glaube, ich weiß, wie man den Rest dieses Algorithmus schreibt!
Hier ist der Arbeitsalgorithmus:
let diskI = disk.length - 1 let emptyI = 0 while (true) { while (disk[diskI] == '.') { diskI-- } disk[empty[emptyI]] = disk[diskI] disk[diskI] = '.' emptyI++ diskI-- if (disk.slice(empty[emptyI],empty[emptyI] + 10).every(el => el == '.')) { break; } }
Wie es funktioniert:
Two trackers: - one for my place in the disk - one for my place in the list of empty slots Do until manually escaped Do as long as the current place in the disk is an empty slot Adjust the tracker one to the left Swap the values at each tracker Decrement the disk tracker Increment the empty tracker If there are 9 empty slots contiguous with the current empty slot Escape the loop
Zum Glück sehe ich die gleiche Ausgabe wie in beiden Beispielen!
Das scheint ziemlich einfach und unkompliziert zu sein:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
Im Pseudocode:
Extract all values up to the first empty cell Iterate through each value, amassing a total Increment the accumulator by the product of the value and its index
Erfolg! Es generiert die richtige Antwort für die Beispieleingabe!
Wird das auch für meine Rätseleingabe gelten?
...
JA!!!
Woohoo!!!
Was wird die Wendung für Teil Zwei sein? Eine leichte Regelanpassung oder eine Größenherausforderung?
Waren Teile. Jetzt ganz.
Dies erfordert definitiv eine Anpassung meines Algorithmus.
Wahrscheinlich robustere Verfolgung der Größe von Lücken und Blöcken.
Ich hat nachverfolgt, wo sich jede Leerstelle befand.
Ich denke, ich muss nachverfolgen, wo und wie groß jeder Leerraum ist.
Wie würde das aussehen?
Kratz das. Vielleicht neue Strategie.
Am ersten Beispiel:
12345
Die Dateiblockgrößen sind ungerade Zahlen:
0..111....22222
Die leeren Zellengrößen sind die geraden Zahlen:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
Beginnend am Ende der ungeraden Zahlen und am Anfang der geraden Zahlen suche ich nach einer geraden Zahl, die größer oder gleich der ungeraden Zahl ist:
022111222......
Ich finde sofort eine Übereinstimmung.
Als Ergebnis:
0099811188827773336446555566..............
Diese Strategie wird definitiv nicht funktionieren.
Mir gefallen die Auswirkungen auf die Leistung nicht.
Aber ich vertraue darauf, dass es funktionieren wird ... solange es nicht mehr läuft.
Für jede Nummer in der Festplatteneingabe werde ich als Listenelement Folgendes aufzeichnen:
Als Beispiel:
let diskI = disk.length - 1 let emptyI = 0 while (true) { while (disk[diskI] == '.') { diskI-- } disk[empty[emptyI]] = disk[diskI] disk[diskI] = '.' emptyI++ diskI-- if (disk.slice(empty[emptyI],empty[emptyI] + 10).every(el => el == '.')) { break; } }
Wird:
Two trackers: - one for my place in the disk - one for my place in the list of empty slots Do until manually escaped Do as long as the current place in the disk is an empty slot Adjust the tracker one to the left Swap the values at each tracker Decrement the disk tracker Increment the empty tracker If there are 9 empty slots contiguous with the current empty slot Escape the loop
Ew, lass uns das aufräumen:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
Ich werde Lücken von Dateiblöcken anhand des Datentyps unterscheiden.
Das Verschieben von Dateiblöcken sieht in einer geänderten Beispieleingabe so aus:
Extract all values up to the first empty cell Iterate through each value, amassing a total Increment the accumulator by the product of the value and its index
Dies umfasst jeweils 100.000 Iterationen:
Beides sind sehr kostspielige Aufgaben.
Aber es ist die einzige Möglichkeit, die mir einfällt, um dieses Rätsel zu lösen.
Das soll also mein Ansatz sein.
Hier ist das JavaScript, das mir die obige Datenarchitektur ermöglicht:
2333133121414131402
Wie beginne und beende ich meine Hauptschleife?
Versuchen Sie, jede Datei genau einmal in der Reihenfolge absteigender Datei-ID-Nummer zu verschieben, beginnend mit der Datei mit der höchsten Datei-ID-Nummer
Scheint so, als würde die Bewegung von hinten nach vorne das tun, was ich brauche.
Dieses for-Schleifengerüst sollte funktionieren:
[2,4,1,4,2,5,5,3,5,2]
[3,3,3,1,1,1,1,1,0]
Diese zweite Klausel im if war mein letzter Debug. Die niedrigsten IDs wurden zu früh eingestellt.
Mir wurde klar, dass ich die Fragmentierung meiner Festplatte nahezu in Echtzeit miterleben musste. Zumindest ein Protokoll davon, wie in der Beispiel-Komplettlösung.
Zum Glück war das Codieren nicht schwierig. Nur der Teil, in dem ich zwei Indizes verwechselt habe und eine wirklich seltsame Ausgabe gesehen habe:
12345
Es funktioniert großartig! Ich konnte sehen, wohin Dateien verschoben wurden, und Fehler in meinem Code viel einfacher beheben!
0..111....22222
Es sieht so aus, als ob mein Algorithmus zum Verschieben von Dateien funktioniert!
Der letzte Schritt besteht darin, die neue Prüfsumme zu berechnen.
Durch eine doppelte Reduzierung:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
Auf der Beispiel-Puzzle-Eingabe? JA!
Zu meinem Rätsel-Input?
...
YEEESSSSSS!
Wow. Ich bin überrascht. Die Zahl, die ich für Teil 2 eingereicht habe, ist fast identisch mit Teil 1. Ich dachte, sie wäre höher.
Ich bin nicht daran interessiert, weitere Nachforschungen anzustellen.
Ich nehme lieber meine zwei hart verdienten goldenen Sterne und gehe zu Tag 10.
Byeeeee Tag 9!
Das obige ist der detaillierte Inhalt vonFestplattenfragmente. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!