Advent of Code 2024 Day 9
Part 1
A three-phase gauntlet. Exciting!??
The phases as I see them spelled out:
- Represent the memory as a list
- Move values from end to beginning
- Walk the line to calculate the checksum
None of it feels particularly difficult.
And some of it actually seems like yet another fun algorithmic challenge!
Making the list
I want to turn this:
12345
Into this:
0..111....22222
I need to consider:
- Using a loop
- Checking for even and odd indices
- Incrementing a value by 1, starting from 0
Here's my disk-generating algorithm:
let id = 0 let disk = [] for (let i = 0; i <p>Works like a charm!</p> <h4> Moving values from end to beginning </h4> <p>What would make this easier is having a list of all empty places on the disk.</p> <p>I need to update my algorithm in two places:</p> <ol> <li>A new variable: let empty = [] </li> <li>A new action after inserting a .: empty.push(disk.length - 1) </li> </ol> <p>Testing it on the example shows the expected index numbers of each .!</p> <p>This is the list I'll iterate through as I move values from the end of the list to the beginning and onward.</p> <p>But wait.</p> <p>This may be more difficult that I thought.</p> <p>How will I know when to stop trying to move values?</p>
- Do I iterate through the list of empty indices? When should I stop?
- Do I iterate backwards through the disks? When should I stop?
An epiphany: the magic number 10
This is the last state of the short example:
022111222......
And of the first example:
0099811188827773336446555566..............
Which means there comes a point where all id's are on the left and all empty spaces are on the right.
How would I check for that state?
Enter: the number 10.
The amount of contiguous empty spaces will never be higher than 9.
So, if I come across an empty space, look forward 9 spaces (or to the end of the disk list), and see all empty spaces, I know I'll have finished fragmenting.
I think I know how to write the rest of this algorithm!
Writing my fragmentation algorithm
Here's the working algorithm:
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; } }
How it works:
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
Thankfully, I see the same output as in both examples!
Calculating the checksum
This seems fairly easy and straightforward:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
In 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
Success! It generates the correct answer for the example input!
Will it do the same for my puzzle input?
...
YES!!!
Woohoo!!!
What will the twist be for Part Two? A slight rule adjustment or some challenge of scale?
Part 2
An interesting twist
Was parts. Now whole.
This will definitely require some adjustment of my algorithm.
Probably more robust tracking of sizes of gaps and blocks.
Working through my first strategy
I was tracking where each empty was.
I think I need to track where - and how big - each empty is.
What would that look like?
Scratch that. Maybe new strategy.
Using the first example:
12345
The file block sizes are the odd numbers:
0..111....22222
The empty cell sizes are the even numbers:
let id = 0 let disk = [] for (let i = 0; i <p>Starting from the end of the odd numbers and the beginning of the even numbers, I look for an even number greater than or equal to the odd number:<br> </p> <pre class="brush:php;toolbar:false">022111222......
I immediately find a match.
As a result:
- The odd number moves
- The even number decreases
- But now the two odd numbers don't have a gap
- And I have lost the second 2s ID
0099811188827773336446555566..............
This strategy definitely won't work.
Working through my second strategy
I don't like the performance implications of this one.
But I trust it will work...as long as it finishes running.
For each number in the disk input, I'll record as a list item:
- File block or empty cell
- Length
- ID
As an example:
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; } }
Will become:
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, let's clean that up:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
I will distinguish gaps from file blocks by way of data type.
Moving file blocks will look like this in an altered example input:
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
This will involve in each 100k iterations:
- Searching for items in a large array
- Mutating an array in-place
Both are very costly tasks.
But it's the only way I can think of to solve this puzzle.
So, this shall be my approach.
Codifying my strategy
Here's the JavaScript that gets me the above data architecture:
2333133121414131402
How will I start and end my main loop?
Attempt to move each file exactly once in order of decreasing file ID number starting with the file with the highest file ID number
Seems like moving back-to-front will do what I need.
This for loop skeleton should work:
[2,4,1,4,2,5,5,3,5,2]
Find, move and replace
[3,3,3,1,1,1,1,1,0]
That second clause in the if was my last debug. It was putting the lowest IDs too early.
Coding a disk-printer
I realized I had to see my disk being fragmented in near-real-time. At least a log of it, like in the example walkthrough.
Thankfully, coding it wasn't difficult. Just the part where I mixed up two indices and saw some real weird output:
12345
- I build up a string
- Based on the type of item in disk
- Either way I make an array and fill it with either .s or the block's ID
It works great! I could see where files were being moved, and troubleshoot my code much easier!
Liking what I see
0..111....22222
It looks like my file-moving algorithm works!
Last step is to calculate the new checksum.
Lastly, more maths
By way of a double-reduce:
let id = 0 let disk = [] for (let i = 0; i
- The first reduce gets me a spread-out array of ids and .s
- The second reduce performs the appropriate math when the item is an id and no math when it's a .
Does it work?
On the example puzzle input? YES!
On my puzzle input?
...
YEEESSSSSS!
Wow. I'm surprised. The number I submitted for Part 2 is almost identical to Part 1. I thought it would be higher.
I'm not interested in investigating further.
I'd rather take my two hard-earned gold stars and walk along to Day 10.
Byeeeeee Day 9!
The above is the detailed content of Disk Fragments. For more information, please follow other related articles on the PHP Chinese website!

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Notepad++7.3.1
Easy-to-use and free code editor

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.
