Day 9: Disk Fragmenter
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You are viewing a single thread.
View all comments 2 points
C#
public class Day09 : Solver
{
private string data;
public void Presolve(string input) {
data = input.Trim();
}
public string SolveFirst() {
var arr = new List<int>();
bool file = true;
int file_id = 0;
foreach (var ch in data) {
if (file) {
Enumerable.Range(0, ch - '0').ToList().ForEach(_ => arr.Add(file_id));
file_id++;
} else {
Enumerable.Range(0, ch - '0').ToList().ForEach(_ => arr.Add(-1));
}
file = !file;
}
int from_ptr = arr.Count - 1;
int to_ptr = 0;
while (from_ptr > to_ptr) {
if (arr[to_ptr] != -1) {
to_ptr++;
continue;
}
if (arr[from_ptr] == -1) {
from_ptr--;
continue;
}
arr[to_ptr] = arr[from_ptr];
arr[from_ptr] = -1;
to_ptr++;
from_ptr--;
}
return Enumerable.Range(0, arr.Count)
.Select(block_id => arr[block_id] > 0 ? ((long)arr[block_id]) * block_id : 0)
.Sum().ToString();
}
public string SolveSecond() {
var files = new List<(int Start, int Size, int Id)>();
bool is_file = true;
int file_id = 0;
int block_id = 0;
foreach (var ch in data) {
if (is_file) {
files.Add((block_id, ch - '0', file_id));
file_id++;
}
is_file = !is_file;
block_id += (ch - '0');
}
while (true) {
bool moved = false;
for (int from_ptr = files.Count - 1; from_ptr >= 1; from_ptr--) {
var file = files[from_ptr];
if (file.Id >= file_id) continue;
file_id = file.Id;
for (int to_ptr = 0; to_ptr < from_ptr; to_ptr++) {
if (files[to_ptr + 1].Start - files[to_ptr].Start - files[to_ptr].Size >= file.Size) {
files.RemoveAt(from_ptr);
files.Insert(to_ptr + 1, file with { Start = files[to_ptr].Start + files[to_ptr].Size });
moved = true;
break;
}
}
if (moved) break;
}
if (!moved) break;
}
return files.Select(file => ((long)file.Id) * file.Size * (2 * ((long)file.Start) + file.Size - 1) / 2)
.Sum().ToString();
}
}