// 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 SubDirectories { get; set; } = new List(); public List Files { get; set; } = new List(); 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; } } }