mirror of
https://github.com/parnic/advent-of-code-2022.git
synced 2025-06-16 13:40:13 -05:00
Minor restructure, .net update, add utilities
This commit is contained in:
@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<RootNamespace>aoc2022</RootNamespace>
|
<RootNamespace>aoc2022</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@ -7,7 +7,7 @@ internal class Day01 : Day
|
|||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
List<int> calories = new();
|
List<int> calories = new();
|
||||||
foreach (var line in Util.ReadAllLines("01"))
|
foreach (var line in Util.Parsing.ReadAllLines("01"))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(line))
|
if (string.IsNullOrEmpty(line))
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ internal class Day02 : Day
|
|||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
lines = Util.ReadAllLines("02");
|
lines = Util.Parsing.ReadAllLines("02");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Part1()
|
internal override string Part1()
|
||||||
|
@ -6,7 +6,7 @@ internal class Day03 : Day
|
|||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
sacks = Util.ReadAllLines("03");
|
sacks = Util.Parsing.ReadAllLines("03");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetPriority(char x) => x <= 'Z' ? x - 'A' + 27 : x - 'a' + 1;
|
static int GetPriority(char x) => x <= 'Z' ? x - 'A' + 27 : x - 'a' + 1;
|
||||||
|
@ -6,7 +6,7 @@ internal class Day04 : Day
|
|||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
foreach (var line in Util.ReadAllLines("04"))
|
foreach (var line in Util.Parsing.ReadAllLines("04"))
|
||||||
{
|
{
|
||||||
var assignments = line.Split(',');
|
var assignments = line.Split(',');
|
||||||
var firstAssignment = assignments[0].Split('-');
|
var firstAssignment = assignments[0].Split('-');
|
||||||
|
@ -17,7 +17,7 @@ internal class Day05 : Day
|
|||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
int state = 0;
|
int state = 0;
|
||||||
foreach (var line in Util.ReadAllLines("05"))
|
foreach (var line in Util.Parsing.ReadAllLines("05"))
|
||||||
{
|
{
|
||||||
if (state == 0)
|
if (state == 0)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ internal class Day06 : Day
|
|||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
buffer = Util.ReadAllText("06");
|
buffer = Util.Parsing.ReadAllText("06");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FindDistinct(string buf, int distinctLen)
|
private static int FindDistinct(string buf, int distinctLen)
|
||||||
|
30
src/07.cs
30
src/07.cs
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
internal class Day07 : Day
|
internal class Day07 : Day
|
||||||
{
|
{
|
||||||
private class file
|
private class fileInfo
|
||||||
{
|
{
|
||||||
public long size;
|
public long size;
|
||||||
// ReSharper disable once NotAccessedField.Local
|
// ReSharper disable once NotAccessedField.Local
|
||||||
@ -11,11 +11,11 @@ internal class Day07 : Day
|
|||||||
public override string ToString() => $"{name}, {size:N0}b";
|
public override string ToString() => $"{name}, {size:N0}b";
|
||||||
}
|
}
|
||||||
|
|
||||||
private class dir
|
private class dirInfo
|
||||||
{
|
{
|
||||||
public dir? outer;
|
public dirInfo? outer;
|
||||||
public readonly List<dir> dirs = new();
|
public readonly List<dirInfo> dirs = new();
|
||||||
public readonly List<file> files = new();
|
public readonly List<fileInfo> files = new();
|
||||||
public string name = string.Empty;
|
public string name = string.Empty;
|
||||||
|
|
||||||
public long size => files.Sum(x => x.size) + dirs.Sum(x => x.size);
|
public long size => files.Sum(x => x.size) + dirs.Sum(x => x.size);
|
||||||
@ -23,13 +23,13 @@ internal class Day07 : Day
|
|||||||
public override string ToString() => $"{name}, {size:N0}b, {dirs.Count} dir{(dirs.Count == 1 ? "" : "s")}, {files.Count} file{(files.Count == 1 ? "" : "s")}{(outer != null ? $", parent '{outer.name}'" : "")}";
|
public override string ToString() => $"{name}, {size:N0}b, {dirs.Count} dir{(dirs.Count == 1 ? "" : "s")}, {files.Count} file{(files.Count == 1 ? "" : "s")}{(outer != null ? $", parent '{outer.name}'" : "")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly dir rootDir = new() {name = "/"};
|
private readonly dirInfo rootDirInfo = new() {name = "/"};
|
||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
dir? curr = null;
|
dirInfo? curr = null;
|
||||||
|
|
||||||
foreach (var line in Util.ReadAllLines("07"))
|
foreach (var line in Util.Parsing.ReadAllLines("07"))
|
||||||
{
|
{
|
||||||
if (line.StartsWith("$"))
|
if (line.StartsWith("$"))
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ internal class Day07 : Day
|
|||||||
{
|
{
|
||||||
if (arg == "/")
|
if (arg == "/")
|
||||||
{
|
{
|
||||||
curr = rootDir;
|
curr = rootDirInfo;
|
||||||
}
|
}
|
||||||
else if (arg == "..")
|
else if (arg == "..")
|
||||||
{
|
{
|
||||||
@ -62,17 +62,17 @@ internal class Day07 : Day
|
|||||||
var parts = line.Split(' ');
|
var parts = line.Split(' ');
|
||||||
if (parts[0] == "dir")
|
if (parts[0] == "dir")
|
||||||
{
|
{
|
||||||
curr!.dirs.Add(new dir() { name = parts[1], outer = curr });
|
curr!.dirs.Add(new dirInfo() { name = parts[1], outer = curr });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
curr!.files.Add(new file { size = long.Parse(parts[0]), name = parts[1] });
|
curr!.files.Add(new fileInfo { size = long.Parse(parts[0]), name = parts[1] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<dir> GetCandidates(dir root, long? threshold = null)
|
private static IEnumerable<dirInfo> GetCandidates(dirInfo root, long? threshold = null)
|
||||||
{
|
{
|
||||||
if (threshold == null || root.size <= threshold)
|
if (threshold == null || root.size <= threshold)
|
||||||
{
|
{
|
||||||
@ -95,15 +95,15 @@ internal class Day07 : Day
|
|||||||
|
|
||||||
internal override string Part1()
|
internal override string Part1()
|
||||||
{
|
{
|
||||||
List<dir> candidates = new(GetCandidates(rootDir, 100000));
|
List<dirInfo> candidates = new(GetCandidates(rootDirInfo, 100000));
|
||||||
|
|
||||||
return $"Sum of directories below 100,000 bytes: <+white>{candidates.Sum(x => x.size)}";
|
return $"Sum of directories below 100,000 bytes: <+white>{candidates.Sum(x => x.size)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Part2()
|
internal override string Part2()
|
||||||
{
|
{
|
||||||
List<dir> flatDirList = new(GetCandidates(rootDir));
|
List<dirInfo> flatDirList = new(GetCandidates(rootDirInfo));
|
||||||
var rootSize = rootDir.size;
|
var rootSize = rootDirInfo.size;
|
||||||
const int totalSize = 70000000;
|
const int totalSize = 70000000;
|
||||||
var currentFreeSpace = totalSize - rootSize;
|
var currentFreeSpace = totalSize - rootSize;
|
||||||
const int totalNeededFreeSpace = 30000000;
|
const int totalNeededFreeSpace = 30000000;
|
||||||
|
@ -6,7 +6,7 @@ internal class Day08 : Day
|
|||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
var lines = new List<string>(Util.ReadAllLines("08"));
|
var lines = new List<string>(Util.Parsing.ReadAllLines("08"));
|
||||||
trees = new int[lines.Count][];
|
trees = new int[lines.Count][];
|
||||||
for (int i = 0; i < lines.Count; i++)
|
for (int i = 0; i < lines.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -3,11 +3,9 @@ namespace aoc2022;
|
|||||||
|
|
||||||
internal class DayTemplate : Day
|
internal class DayTemplate : Day
|
||||||
{
|
{
|
||||||
IEnumerable<string>? lines;
|
|
||||||
|
|
||||||
internal override void Parse()
|
internal override void Parse()
|
||||||
{
|
{
|
||||||
lines = Util.ReadAllLines("##");
|
var lines = Util.Parsing.ReadAllLines("##");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Part1()
|
internal override string Part1()
|
||||||
|
119
src/Util.cs
119
src/Util.cs
@ -1,118 +1 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace aoc2022;
|
|
||||||
|
|
||||||
internal static class Util
|
|
||||||
{
|
|
||||||
private static readonly char[] StripPreamble = { (char)8745, (char)9559, (char)9488, };
|
|
||||||
private static readonly Encoding[] StripBOMsFromEncodings = { Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode, };
|
|
||||||
private static void ReadData(string inputName, Action<string> processor)
|
|
||||||
{
|
|
||||||
if (Console.IsInputRedirected)
|
|
||||||
{
|
|
||||||
bool processedSomething = false;
|
|
||||||
for (int i = 0; Console.In.ReadLine() is { } line; i++)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
if (line[0..StripPreamble.Length].SequenceEqual(StripPreamble))
|
|
||||||
{
|
|
||||||
line = line[StripPreamble.Length..];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var encoding in StripBOMsFromEncodings)
|
|
||||||
{
|
|
||||||
if (line.StartsWith(encoding.GetString(encoding.GetPreamble()), StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
line = line.Replace(encoding.GetString(encoding.GetPreamble()), "", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
processor(line);
|
|
||||||
if (!string.IsNullOrEmpty(line))
|
|
||||||
{
|
|
||||||
processedSomething = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processedSomething)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var filename = $"inputs/{inputName}.txt";
|
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
|
||||||
foreach (var line in File.ReadLines(filename))
|
|
||||||
{
|
|
||||||
processor(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeof(Util) is not technically correct since what we need is the "default namespace,"
|
|
||||||
// but "default namespace" is a Project File concept, not a C#/.NET concept, so it's not
|
|
||||||
// accessible at runtime. instead, we assume Util is also part of the "default namespace"
|
|
||||||
var resourceName = $"{typeof(Util).Namespace}.inputs.{inputName}.txt";
|
|
||||||
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
|
|
||||||
using StreamReader reader = new(stream!);
|
|
||||||
while (reader.ReadLine() is { } readLine)
|
|
||||||
{
|
|
||||||
processor(readLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string ReadAllText(string filename)
|
|
||||||
{
|
|
||||||
string contents = string.Empty;
|
|
||||||
ReadData(filename, (line) => contents = line);
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IEnumerable<string> ReadAllLines(string filename)
|
|
||||||
{
|
|
||||||
List<string> lines = new();
|
|
||||||
ReadData(filename, (line) => lines.Add(line));
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IEnumerable<long> ReadAllLinesAsInts(string filename)
|
|
||||||
{
|
|
||||||
return ReadAllLines(filename).Select(long.Parse);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void StartTestSet(string name)
|
|
||||||
{
|
|
||||||
Logger.Log($"<underline>test: {name}<r>");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void StartTest(string label)
|
|
||||||
{
|
|
||||||
Logger.Log($"<magenta>{label}<r>");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void TestCondition(Func<bool> a, bool printResult = true)
|
|
||||||
{
|
|
||||||
if (a.Invoke() == false)
|
|
||||||
{
|
|
||||||
Debug.Assert(false);
|
|
||||||
if (printResult)
|
|
||||||
{
|
|
||||||
Logger.Log("<red>x<r>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (printResult)
|
|
||||||
{
|
|
||||||
Logger.Log("<green>✓<r>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
51
src/Util/Bisect.cs
Normal file
51
src/Util/Bisect.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace aoc2022.Util;
|
||||||
|
|
||||||
|
public static class Bisect
|
||||||
|
{
|
||||||
|
// Bisect takes a known-good low and known-bad high value as the bounds
|
||||||
|
// to bisect, and a function to test each value for success or failure.
|
||||||
|
// If the function succeeds, the value is adjusted toward the maximum,
|
||||||
|
// and if the function fails, the value is adjusted toward the minimum.
|
||||||
|
// The final value is returned when the difference between the success
|
||||||
|
// and the failure is less than or equal to the acceptance threshold
|
||||||
|
// (usually 1, for integers).
|
||||||
|
public static double Find(double low, double high, double threshold, Func<double, bool> tryFunc)
|
||||||
|
{
|
||||||
|
while (System.Math.Abs(high - low) > threshold)
|
||||||
|
{
|
||||||
|
var currVal = low + ((high - low) / 2);
|
||||||
|
var success = tryFunc(currVal);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
low = currVal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
high = currVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Find(long low, long high, long threshold, Func<long, bool> tryFunc)
|
||||||
|
{
|
||||||
|
while (System.Math.Abs(high - low) > threshold)
|
||||||
|
{
|
||||||
|
var currVal = low + ((high - low) / 2);
|
||||||
|
var success = tryFunc(currVal);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
low = currVal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
high = currVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
}
|
38
src/Util/Combinatorics.cs
Normal file
38
src/Util/Combinatorics.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
namespace aoc2022.Util;
|
||||||
|
|
||||||
|
public static class Combinatorics
|
||||||
|
{
|
||||||
|
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IList<T> list)
|
||||||
|
{
|
||||||
|
Action<IList<T>, int>? helper = null;
|
||||||
|
List<IEnumerable<T>> res = new();
|
||||||
|
|
||||||
|
helper = (arr, n) =>
|
||||||
|
{
|
||||||
|
if (n == 1)
|
||||||
|
{
|
||||||
|
var tmp = new T[arr.Count];
|
||||||
|
arr.CopyTo(tmp, 0);
|
||||||
|
res.Add(tmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
helper!(arr, n - 1);
|
||||||
|
if (n % 2 == 1)
|
||||||
|
{
|
||||||
|
(arr[i], arr[n - 1]) = (arr[n - 1], arr[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(arr[0], arr[n - 1]) = (arr[n - 1], arr[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
helper(list, list.Count);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
46
src/Util/Math.cs
Normal file
46
src/Util/Math.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace aoc2022.Util;
|
||||||
|
|
||||||
|
public static class Math
|
||||||
|
{
|
||||||
|
public static ulong GCD(ulong a, ulong b)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a1 = a;
|
||||||
|
a = b;
|
||||||
|
b = a1 % b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ulong LCM(params ulong[] nums)
|
||||||
|
{
|
||||||
|
var num = nums.Length;
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
return nums[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = lcm(nums[0], nums[1]);
|
||||||
|
for (var i = 2; i < num; i++)
|
||||||
|
{
|
||||||
|
ret = lcm(nums[i], ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong lcm(ulong a, ulong b)
|
||||||
|
{
|
||||||
|
return (a * b) / GCD(a, b);
|
||||||
|
}
|
||||||
|
}
|
88
src/Util/Parsing.cs
Normal file
88
src/Util/Parsing.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace aoc2022.Util;
|
||||||
|
|
||||||
|
public static class Parsing
|
||||||
|
{
|
||||||
|
private static readonly char[] StripPreamble = { (char)8745, (char)9559, (char)9488, };
|
||||||
|
private static readonly Encoding[] StripBOMsFromEncodings = { Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode, };
|
||||||
|
private static void ReadData(string inputName, Action<string> processor)
|
||||||
|
{
|
||||||
|
if (Console.IsInputRedirected)
|
||||||
|
{
|
||||||
|
bool processedSomething = false;
|
||||||
|
for (int i = 0; Console.In.ReadLine() is { } line; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (line[0..StripPreamble.Length].SequenceEqual(StripPreamble))
|
||||||
|
{
|
||||||
|
line = line[StripPreamble.Length..];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var encoding in StripBOMsFromEncodings)
|
||||||
|
{
|
||||||
|
if (line.StartsWith(encoding.GetString(encoding.GetPreamble()), StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
line = line.Replace(encoding.GetString(encoding.GetPreamble()), "", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processor(line);
|
||||||
|
if (!string.IsNullOrEmpty(line))
|
||||||
|
{
|
||||||
|
processedSomething = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processedSomething)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename = $"inputs/{inputName}.txt";
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
foreach (var line in File.ReadLines(filename))
|
||||||
|
{
|
||||||
|
processor(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeof(Logger) is not technically correct since what we need is the "default namespace,"
|
||||||
|
// but "default namespace" is a Project File concept, not a C#/.NET concept, so it's not
|
||||||
|
// accessible at runtime. instead, we assume Logger is also part of the "default namespace"
|
||||||
|
var resourceName = $"{typeof(Logger).Namespace}.inputs.{inputName}.txt";
|
||||||
|
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
|
||||||
|
using StreamReader reader = new(stream!);
|
||||||
|
while (reader.ReadLine() is { } readLine)
|
||||||
|
{
|
||||||
|
processor(readLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ReadAllText(string filename)
|
||||||
|
{
|
||||||
|
string contents = string.Empty;
|
||||||
|
ReadData(filename, (line) => contents = line);
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<string> ReadAllLines(string filename)
|
||||||
|
{
|
||||||
|
List<string> lines = new();
|
||||||
|
ReadData(filename, (line) => lines.Add(line));
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<long> ReadAllLinesAsInts(string filename)
|
||||||
|
{
|
||||||
|
return ReadAllLines(filename).Select(long.Parse);
|
||||||
|
}
|
||||||
|
}
|
35
src/Util/Testing.cs
Normal file
35
src/Util/Testing.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace aoc2022.Util;
|
||||||
|
|
||||||
|
public static class Testing
|
||||||
|
{
|
||||||
|
internal static void StartTestSet(string name)
|
||||||
|
{
|
||||||
|
Logger.Log($"<underline>test: {name}<r>");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void StartTest(string label)
|
||||||
|
{
|
||||||
|
Logger.Log($"<magenta>{label}<r>");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void TestCondition(Func<bool> a, bool printResult = true)
|
||||||
|
{
|
||||||
|
if (a.Invoke() == false)
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
if (printResult)
|
||||||
|
{
|
||||||
|
Logger.Log("<red>x<r>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (printResult)
|
||||||
|
{
|
||||||
|
Logger.Log("<green>✓<r>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user