Part 1 Day 9
This commit is contained in:
@@ -21,7 +21,6 @@ internal class BridgeRepair : Problem<ulong, ulong>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//This does not work
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
foreach (var (target, nums) in _data)
|
foreach (var (target, nums) in _data)
|
||||||
|
|||||||
@@ -1,25 +1,248 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day9;
|
namespace AdventOfCode.Problems.AOC2024.Day9;
|
||||||
//[ProblemInfo(2024, 9, "Disk Fragmenter")]
|
|
||||||
internal class DiskFragmenter : Problem
|
[ProblemInfo(2024, 9, "Disk Fragmenter")]
|
||||||
|
internal class DiskFragmenter : Problem<long, long>
|
||||||
{
|
{
|
||||||
|
private int[] _data = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var data = Expand(_data);
|
||||||
|
Compact(data);
|
||||||
|
Part1 = ComputeHash(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
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<Block> 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<int>(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<Block> ExpandBlocks(int[] data)
|
||||||
|
{
|
||||||
|
var blocks = new List<Block>();
|
||||||
|
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<Block> 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<Block> 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<Block> 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()
|
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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
global using AdventOfCode.Runner;
|
global using AdventOfCode.Runner;
|
||||||
global using AdventOfCode.Runner.Attributes;
|
global using AdventOfCode.Runner.Attributes;
|
||||||
|
global using AdventOfCode.Utils;
|
||||||
|
|
||||||
|
|
||||||
var runner = new AOCRunner();
|
var runner = new AOCRunner();
|
||||||
runner.RenderInteractiveMenu();
|
runner.RenderInteractiveMenu();
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ using System.Threading.Tasks;
|
|||||||
namespace AdventOfCode.Utils;
|
namespace AdventOfCode.Utils;
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static string AsJoinedString(this object[] data, string delim = ", ")
|
|
||||||
|
|
||||||
|
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
|
||||||
{
|
{
|
||||||
return string.Join(delim, data);
|
return string.Join(delim, data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user