205 lines
5.5 KiB
C#
205 lines
5.5 KiB
C#
// See https://aka.ms/new-console-template for more information
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Xml;
|
|
|
|
Console.WriteLine("Hello, World!");
|
|
|
|
Directory exampleRoot = LoadData("example-input.txt");
|
|
Directory puzzleRoot = LoadData("puzzle-input.txt");
|
|
|
|
Console.WriteLine(String.Format("Part01: Example({0}), Puzzle({1})", Part01(exampleRoot, 100000), Part01(puzzleRoot, 100000)));
|
|
|
|
Console.WriteLine(String.Format("Part02: Example({0}), Puzzle({1})" , Part02(exampleRoot, 70000000 - exampleRoot.Size, 30000000, exampleRoot.Size)
|
|
, Part02(puzzleRoot, 70000000 - puzzleRoot.Size, 30000000, puzzleRoot.Size)));
|
|
|
|
int Part01(Directory root, int maxsize)
|
|
{
|
|
int returnSize = 0;
|
|
int size = 0;
|
|
|
|
foreach (var file in root.Files)
|
|
{
|
|
size += file.Size;
|
|
}
|
|
foreach (var subdir in root.SubDirectories)
|
|
{
|
|
size += subdir.Size;
|
|
}
|
|
|
|
if (size < maxsize) returnSize += size;
|
|
|
|
foreach (var subdir in root.SubDirectories)
|
|
{
|
|
returnSize += Part01(subdir, maxsize);
|
|
}
|
|
|
|
return returnSize;
|
|
}
|
|
|
|
int Part02(Directory root, int unusedSpace, int targetUnusedSpace, int returnSize)
|
|
{
|
|
if (unusedSpace + root.Size > targetUnusedSpace)
|
|
{
|
|
returnSize = Int32.Min(returnSize, root.Size);
|
|
}
|
|
|
|
|
|
foreach (var subdir in root.SubDirectories)
|
|
{
|
|
returnSize = Int32.Min(returnSize, Part02(subdir, unusedSpace, targetUnusedSpace, returnSize));
|
|
}
|
|
|
|
return returnSize;
|
|
}
|
|
|
|
Directory LoadData(string fileName)
|
|
{
|
|
Directory root = new Directory("/", null);
|
|
Directory currentDir = root;
|
|
|
|
using (StreamReader reader = System.IO.File.OpenText(fileName))
|
|
{
|
|
while (!reader.EndOfStream)
|
|
{
|
|
string? line = reader.ReadLine();
|
|
if (line == null) throw new InvalidDataException();
|
|
if (line.Length == 0) continue;
|
|
|
|
// We should be reading commands here
|
|
if (line.StartsWith('$'))
|
|
{
|
|
var split = line.Split(' ');
|
|
|
|
if (split[1].StartsWith("cd"))
|
|
{
|
|
if (split.Length != 3)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
currentDir = HandleChangeDirectory(reader, split[2], currentDir);
|
|
}
|
|
else if (split[1].StartsWith("ls"))
|
|
{
|
|
currentDir = HandleListDirectory(reader, currentDir);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return root;
|
|
}
|
|
|
|
Directory HandleListDirectory(StreamReader reader, Directory currentDir)
|
|
{
|
|
while (!reader.EndOfStream && reader.Peek() != '$')
|
|
{
|
|
string? line = reader.ReadLine();
|
|
if (line == null) throw new InvalidDataException();
|
|
|
|
var split = line.Split(" ");
|
|
|
|
int size = 0;
|
|
|
|
if (split[0].StartsWith("dir"))
|
|
{
|
|
if (currentDir.SubDirectories.Exists(x => x.Name.StartsWith(split[1])))
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
currentDir.SubDirectories.Add(new Directory(split[1], currentDir));
|
|
}
|
|
else if (Int32.TryParse(split[0], out size))
|
|
{
|
|
if (currentDir.Files.Exists(x => x.Name == split[1]))
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
currentDir.Files.Add(new File(split[1], size));
|
|
}
|
|
else
|
|
{ throw new InvalidDataException(); }
|
|
}
|
|
|
|
return currentDir;
|
|
}
|
|
|
|
Directory HandleChangeDirectory(StreamReader reader, string argument, Directory currentDir)
|
|
{
|
|
switch (argument)
|
|
{
|
|
case "/":
|
|
while (currentDir != null && !currentDir.Name.StartsWith("/"))
|
|
{
|
|
if (currentDir.Parent == null) throw new InvalidDataException();
|
|
currentDir = currentDir.Parent;
|
|
}
|
|
return currentDir;
|
|
|
|
case "..":
|
|
if (currentDir.Parent == null)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
currentDir = currentDir.Parent;
|
|
return currentDir;
|
|
|
|
default:
|
|
foreach (var subdir in currentDir.SubDirectories)
|
|
{
|
|
if (subdir.Name == argument)
|
|
{
|
|
currentDir = subdir;
|
|
return currentDir;
|
|
}
|
|
}
|
|
throw new InvalidDataException();
|
|
}
|
|
}
|
|
|
|
class File
|
|
{
|
|
public string Name { get; set; }
|
|
public int Size { get; set; }
|
|
|
|
public File(string name, int size)
|
|
{
|
|
Name = name;
|
|
Size = size;
|
|
}
|
|
}
|
|
class Directory
|
|
{
|
|
public List<Directory> SubDirectories { get; set; } = new List<Directory>();
|
|
public List<File> Files { get; set; } = new List<File>();
|
|
public Directory? Parent { get; set; } = null;
|
|
|
|
public string Name { get; set; }
|
|
|
|
public Directory(string name, Directory parent) { Name = name; Parent = parent; }
|
|
|
|
public int Size
|
|
{
|
|
get
|
|
{
|
|
int size = 0;
|
|
|
|
foreach (var subdir in SubDirectories)
|
|
{
|
|
size += subdir.Size;
|
|
}
|
|
foreach (var file in Files)
|
|
{
|
|
size += file.Size;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
}
|
|
} |