initial commit, day 10
This commit is contained in:
174
dotnet/08/08a.cs
Normal file
174
dotnet/08/08a.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
Main1();
|
||||
Main2();
|
||||
|
||||
|
||||
void Main1()
|
||||
{
|
||||
var map = LoadMap(Path.Join("..", "..", "08a.txt"));
|
||||
HashSet<Point> antinodes = new();
|
||||
foreach (var (ch, points) in map.Antennae)
|
||||
{
|
||||
for (int i = 0; i < points.Count-1; i++)
|
||||
{
|
||||
for (int j = i+1; j < points.Count; j++)
|
||||
{
|
||||
antinodes.UnionWith(points[i].GetAntinodes(points[j]).Where(map.Validate));
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {antinodes.Count}");
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
var map = LoadMap(Path.Join("..", "..", "08a.txt"));
|
||||
HashSet<Point> antinodes = new();
|
||||
foreach (var (ch, points) in map.Antennae)
|
||||
{
|
||||
for (int i = 0; i < points.Count-1; i++)
|
||||
{
|
||||
for (int j = i+1; j < points.Count; j++)
|
||||
{
|
||||
antinodes.UnionWith(points[i].GetAntinodes2(points[j], map));
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {antinodes.Count}");
|
||||
}
|
||||
|
||||
Map LoadMap(string filepath)
|
||||
{
|
||||
var lines = File.ReadAllLines(filepath)
|
||||
.Where(l => !string.IsNullOrWhiteSpace(l))
|
||||
.Select(s => s.Trim())
|
||||
.ToList();
|
||||
Map map = new();
|
||||
foreach (var (line, row) in lines.Select((l, i) => (l, i)))
|
||||
{
|
||||
foreach (var (c, col) in line.Select((ch, i) => (ch, i)))
|
||||
{
|
||||
if (c != '.')
|
||||
{
|
||||
Point p = new(row, col);
|
||||
if (map.Antennae.TryGetValue(c, out var points))
|
||||
{
|
||||
points.Add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Antennae[c] = new(Enumerable.Repeat(p, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map.Width = lines[0].Length;
|
||||
map.Height = lines.Count;
|
||||
return map;
|
||||
}
|
||||
|
||||
public static class Stuff
|
||||
{
|
||||
//I forgot the good algorithm
|
||||
public static int TerribleGcf(int first, int second)
|
||||
{
|
||||
int gcf = 1;
|
||||
while (first % 2 == 0 && second % 2 == 0)
|
||||
{
|
||||
gcf *= 2;
|
||||
first /= 2;
|
||||
second /= 2;
|
||||
}
|
||||
for (int prime = 3; prime < first && prime < second; prime += 2)
|
||||
{
|
||||
while (first % prime == 0 && second % prime == 0)
|
||||
{
|
||||
gcf *= prime;
|
||||
first /= prime;
|
||||
second /= prime;
|
||||
}
|
||||
}
|
||||
return gcf;
|
||||
}
|
||||
//I had to look up the right way
|
||||
public static int EuclideanGcf(int first, int second)
|
||||
{
|
||||
if (first == 0 || second == 0)
|
||||
return 0;
|
||||
first = Math.Abs(first);
|
||||
second = Math.Abs(second);
|
||||
while (first != second)
|
||||
{
|
||||
if (second > first)
|
||||
{
|
||||
first = first ^ second;
|
||||
second = first ^ second;
|
||||
first = first ^ second;
|
||||
}
|
||||
first = first - second;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
class Map
|
||||
{
|
||||
public Dictionary<char, List<Point>> Antennae = new();
|
||||
public int Width;
|
||||
public int Height;
|
||||
public Map()
|
||||
{
|
||||
|
||||
}
|
||||
public bool Validate(Point p)
|
||||
=> p.Row >= 0 && p.Row < Width && p.Col >= 0 && p.Col < Height;
|
||||
}
|
||||
|
||||
record struct Point(int Row, int Col)
|
||||
{
|
||||
public static Vector operator -(Point first, Point second)
|
||||
=> new(first.Row - second.Row, first.Col - second.Col);
|
||||
public static Point operator +(Point first, Vector second)
|
||||
=> new(first.Row + second.Row, first.Col + second.Col);
|
||||
public static Point operator -(Point first, Vector second)
|
||||
=> new(first.Row - second.Row, first.Col - second.Col);
|
||||
public readonly IEnumerable<Point> GetAntinodes(Point other)
|
||||
{
|
||||
var diff = this - other;
|
||||
yield return this + diff;
|
||||
yield return other - diff;
|
||||
if (diff.Row % 3 == 0 && diff.Col % 3 == 0)
|
||||
{
|
||||
Console.WriteLine("inline");
|
||||
yield return other + (diff / 3);
|
||||
yield return other + (diff * 2 / 3);
|
||||
}
|
||||
}
|
||||
public IEnumerable<Point> GetAntinodes2(Point other, Map map)
|
||||
{
|
||||
var diff = this - other;
|
||||
// diff /= Stuff.TerribleGcf(diff.Row, diff.Col);
|
||||
diff /= Stuff.EuclideanGcf(diff.Row, diff.Col);
|
||||
var running = this;
|
||||
while (map.Validate(running))
|
||||
{
|
||||
yield return running;
|
||||
running -= diff;
|
||||
}
|
||||
running = this + diff;
|
||||
while (map.Validate(running))
|
||||
{
|
||||
yield return running;
|
||||
running += diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record struct Vector(int Row, int Col)
|
||||
{
|
||||
public static Vector operator +(Vector first, Vector second)
|
||||
=> new(first.Row + second.Row, first.Col + second.Col);
|
||||
public static Vector operator *(Vector first, int second)
|
||||
=> new(first.Row * second, first.Col * second);
|
||||
public static Vector operator /(Vector first, int second)
|
||||
=> new(first.Row / second, first.Col / second);
|
||||
}
|
||||
Reference in New Issue
Block a user