AdventOfCode/Advent Of Code Library/2022/Day 07/DirectoryManager.cs
2022-12-08 09:59:58 +01:00

97 lines
3.4 KiB
C#

namespace AdventOfCodeLibrary._2022.Day_07
{
public class Directory
{
public Directory? ParentDirectory { get; set; }
public string Name { get; set; } = string.Empty;
public List<Directory> Directories { get; set; } = new();
public List<File> Files { get; set; } = new();
public int GetSizeOfAllFiles() => Files.Sum(f => f.Size) + Directories.Sum(d => d.GetSizeOfAllFiles());
}
public struct File
{
public string Name { get; set; }
public int Size { get; set; }
}
internal class DirectoryManager
{
readonly Directory RootDirectory;
Directory CurrentDirectory;
internal DirectoryManager()
{
RootDirectory = new Directory { Name = "/", ParentDirectory = null };
CurrentDirectory = RootDirectory;
}
internal void ParseTerminalOutput(string[] lines)
{
for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
{
string[] parts = lines[lineIndex].Split(' ');
// it is a command
if (parts[0] == "$")
{
// move to other folder
if (parts[1] == "cd")
{
switch (parts[2])
{
// go to root
case "/":
CurrentDirectory = RootDirectory;
continue;
// go to parent
case "..":
CurrentDirectory = CurrentDirectory.ParentDirectory;
continue;
// go to sub
default:
CurrentDirectory = CurrentDirectory.Directories.Single(dir => dir.Name == parts[2]);
break;
}
}
// if none of the about, just skip
continue;
}
// if not a command it is the output from the ls command
if (parts[0] == "dir")
{
CurrentDirectory.Directories.Add(new Directory { Name = parts[1], ParentDirectory = CurrentDirectory });
continue;
}
// it should be a number indicating the size of a file
CurrentDirectory.Files.Add(new File { Name = parts[1], Size = Convert.ToInt32(parts[0]) });
}
}
internal string GetDirectoriesWithMaxFilesSize(int maxSize)
{
return GetDirectories(RootDirectory).Where(d => d.GetSizeOfAllFiles() <= maxSize).Sum(d => d.GetSizeOfAllFiles()).ToString();
}
internal string GetDirectoriesClosestTo(int totalSize, int sizeNeeded)
{
sizeNeeded -= totalSize - RootDirectory.GetSizeOfAllFiles();
return GetDirectories(RootDirectory).Where(d => d.GetSizeOfAllFiles() >= sizeNeeded).Min(d => d.GetSizeOfAllFiles()).ToString();
}
private IEnumerable<Directory> GetDirectories(Directory source)
{
yield return source;
foreach (Directory dir in source.Directories.SelectMany(GetDirectories))
{
yield return dir;
}
}
}
}