From a92c9b4478996956d7199dd222512a848c9c051f Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Mon, 16 Dec 2024 23:16:53 -0500 Subject: [PATCH] Part 1 Day 9 --- .../Problems/AOC2024/Day7/BridgeRepair.cs | 1 - .../Problems/AOC2024/Day9/DiskFragmenter.cs | 233 +++++++++++++++++- AdventOfCode/Program.cs | 2 + AdventOfCode/Utils/Extensions.cs | 4 +- 4 files changed, 233 insertions(+), 7 deletions(-) diff --git a/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs b/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs index 876cc35..e3b3c09 100644 --- a/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs +++ b/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs @@ -21,7 +21,6 @@ internal class BridgeRepair : Problem } } - //This does not work public override void CalculatePart2() { foreach (var (target, nums) in _data) diff --git a/AdventOfCode/Problems/AOC2024/Day9/DiskFragmenter.cs b/AdventOfCode/Problems/AOC2024/Day9/DiskFragmenter.cs index 8d21139..521ae22 100644 --- a/AdventOfCode/Problems/AOC2024/Day9/DiskFragmenter.cs +++ b/AdventOfCode/Problems/AOC2024/Day9/DiskFragmenter.cs @@ -1,25 +1,248 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AdventOfCode.Problems.AOC2024.Day9; -//[ProblemInfo(2024, 9, "Disk Fragmenter")] -internal class DiskFragmenter : Problem + +[ProblemInfo(2024, 9, "Disk Fragmenter")] +internal class DiskFragmenter : Problem { + private int[] _data = []; + public override void CalculatePart1() { - throw new NotImplementedException(); + var data = Expand(_data); + Compact(data); + Part1 = ComputeHash(data); } public override void CalculatePart2() { - throw new NotImplementedException(); + var blocks = ExpandBlocks(_data); + CompactV2(blocks); + //Print(blocks); + // Too High: 8838426222802 + Part2 = ComputeHashV2(blocks); + } + + public static void Print(List blocks, int idx = -1) + { + for (int i = 0; i < blocks.Count; i++) + { + Console.ResetColor(); + if(i == idx) + Console.BackgroundColor = ConsoleColor.Green; + if (blocks[i].isEmpty) + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.Write(blocks[i].ToString()); + } + Console.ResetColor(); + Console.WriteLine(); + } + + public static void Print(int[] data) + { + Console.WriteLine(data.Select(x => x == -1 ? " " : x.ToString()).AsJoinedString("").Trim()); + } + + public static int[] Expand(int[] data) + { + var result = new List(data.Sum()); + var isFile = true; + var id = 0; + foreach (var item in data) + { + if (isFile) + result.AddRange(Enumerable.Repeat(id++, item)); + else + result.AddRange(Enumerable.Repeat(-1, item)); + isFile = !isFile; + } + return [.. result]; + } + + public static void Compact(int[] data) + { + var readPos = data.Length - 1; + var writePos = 0; + var curValue = 0; + var isWriting = false; + while (true) + { + if (readPos - 2 < writePos && !isWriting) + break; + if (isWriting) + { + while (writePos < data.Length) + { + if (data[writePos] == -1) + { + data[writePos] = curValue; + data[readPos] = -1; + curValue = -1; + writePos++; + break; + } + writePos++; + } + isWriting = false; + } + else + { + do + { + curValue = data[readPos]; + if (curValue != -1) + { + isWriting = true; + break; + } + readPos--; + } + while (readPos >= 0); + } + } + } + + public static long ComputeHash(int[] data) + { + long hash = 0; + //Compensate to incomplete compaction + long idx = 0; + for (long i = 0; i < data.Length; i++) + { + if (data[i] == -1) + continue; + hash += (idx++) * (long)data[i]; + } + return hash; + } + + public static List ExpandBlocks(int[] data) + { + var blocks = new List(); + var isFile = true; + var id = 0; + foreach (var block in data) + { + if (block == 0) + { + isFile = !isFile; + continue; + } + if (isFile) + blocks.Add(new Block(id++, block)); + else + blocks.Add(new Block(block)); + isFile = !isFile; + } + return blocks; + } + + public static void CompactV2(List blocks) + { + for (int idx = blocks.Count - 1; idx >= 0; idx--) + { + var block = blocks[idx]; + if (block.isEmpty) + continue; + var emptyPos = FindFirstEmptyBlock(block.length, idx, blocks); + if (emptyPos == -1) + continue; + var emptyBlock = blocks[emptyPos]; + //Replace Empty Block + if (emptyBlock.length == block.length) + blocks[emptyPos] = block; + else + { + //Insert and Shrink Empty Block + blocks.Insert(emptyPos, block); + idx += 1; + emptyBlock.length -= block.length; + } + + //Merge Left and Right empty blocks + if (idx + 1 < blocks.Count && blocks[idx + 1].isEmpty && idx - 1 > 0 && blocks[idx - 1].isEmpty) + { + blocks[idx - 1].length += block.length + blocks[idx + 1].length; + blocks.RemoveAt(idx); + blocks.RemoveAt(idx); + idx -= 1; + } + //Extend Right Block + else if (idx + 1 < blocks.Count && blocks[idx + 1].isEmpty) + blocks[idx + 1].length += block.length; + //Extend Left Block + else if (idx - 1 > 0 && blocks[idx - 1].isEmpty) + blocks[idx - 1].length += block.length; + //Insert new Empty Block + else + blocks[idx] = new Block(block.length); + //Print(blocks, idx); + } + + static int FindFirstEmptyBlock(int length, int limit, List blocks) + { + for (int i = 0; i < limit; i++) + { + var block = blocks[i]; + if (block.isEmpty && block.length >= length) + return i; + } + return -1; + } + } + + public static long ComputeHashV2(List blocks) + { + long hash = 0; + long pos = 0; + for (int i = 0; i < blocks.Count; i++) + { + var block = blocks[i]; + if (!block.isEmpty) + { + //There's probably an equation for this + for (int x = 0; x < block.length; x++) + { + hash += block.id * pos++; + } + }else + pos += block.length; + } + + return hash; } public override void LoadInput() { - throw new NotImplementedException(); + _data = ReadInputText("input.txt").Select(x => (int)(x - '0')).ToArray(); } } + +public class Block +{ + public bool isEmpty; + public int id; + public int length; + + public Block(int id, int length) + { + this.id = id; + this.length = length; + } + + public Block(int length) + { + isEmpty = true; + this.length = length; + } + + public override string ToString() + { + return isEmpty ? $"[{length}]" : $"{id}:{length}"; + } +} \ No newline at end of file diff --git a/AdventOfCode/Program.cs b/AdventOfCode/Program.cs index 4786316..7dd9102 100644 --- a/AdventOfCode/Program.cs +++ b/AdventOfCode/Program.cs @@ -1,5 +1,7 @@ global using AdventOfCode.Runner; global using AdventOfCode.Runner.Attributes; +global using AdventOfCode.Utils; + var runner = new AOCRunner(); runner.RenderInteractiveMenu(); diff --git a/AdventOfCode/Utils/Extensions.cs b/AdventOfCode/Utils/Extensions.cs index 3e95de0..80baa42 100644 --- a/AdventOfCode/Utils/Extensions.cs +++ b/AdventOfCode/Utils/Extensions.cs @@ -7,7 +7,9 @@ using System.Threading.Tasks; namespace AdventOfCode.Utils; public static class Extensions { - public static string AsJoinedString(this object[] data, string delim = ", ") + + + public static string AsJoinedString(this IEnumerable data, string delim = ", ") { return string.Join(delim, data); }