namespace AdventOfCode.HelperClasses; public record Coordinate(long X, long Y) { public long GetManhattanDistance(Coordinate other) => GetManhattanDistance(this, other); public static long GetManhattanDistance(Coordinate a, Coordinate b) => Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y); public double GetEuclidianDistance(Coordinate other) => GetEuclidianDistance(this, other); public static double GetEuclidianDistance(Coordinate a, Coordinate b) => Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y)); public static Coordinate operator +(Coordinate left, Coordinate right) => new(left.X + right.X, left.Y + right.Y); public static Coordinate operator -(Coordinate left, Coordinate right) => new(left.X - right.X, left.Y - right.Y); public static Coordinate operator *(Coordinate coord, int amount) => new(coord.X * amount, coord.Y * amount); } public record Coordinate3d(long X, long Y, long Z) { public long GetManhattanDistance(Coordinate3d other) => GetManhattanDistance(this, other); public static long GetManhattanDistance(Coordinate3d a, Coordinate3d b) => Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y) + Math.Abs(a.Z - b.Z); public double GetEuclidianDistance(Coordinate3d other) => GetEuclidianDistance(this, other); public static double GetEuclidianDistance(Coordinate3d a, Coordinate3d b) => Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y) + (a.Z - b.Z) * (a.Z - b.Z)); public static Coordinate3d operator +(Coordinate3d left, Coordinate3d right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z); public static Coordinate3d operator -(Coordinate3d left, Coordinate3d right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z); public static Coordinate3d operator *(Coordinate3d coord, int amount) => new(coord.X * amount, coord.Y * amount, coord.Z * amount); } public record CoordinateNd(long[] Axes) { public long GetManhattanDistance(CoordinateNd other) => GetManhattanDistance(this, other); public static long GetManhattanDistance(CoordinateNd a, CoordinateNd b) => a.Axes.Length == b.Axes.Length ? a.Axes.Zip(b.Axes, (ax, bx) => Math.Abs(ax - bx)).Sum() : throw new DimensionMismatchException(); public double GetEuclidianDistance(CoordinateNd other) => GetEuclidianDistance(this, other); public static double GetEuclidianDistance(CoordinateNd a, CoordinateNd b) => a.Axes.Length == b.Axes.Length ? Math.Sqrt(a.Axes.Zip(b.Axes, (ax, bx) => (ax - bx) * (ax - bx)).Sum()) : throw new DimensionMismatchException(); public static CoordinateNd operator +(CoordinateNd left, CoordinateNd right) => left.Axes.Length == right.Axes.Length ? new CoordinateNd([..left.Axes.Zip(right.Axes, (l, r) => l + r)]) : throw new DimensionMismatchException(); public static CoordinateNd operator -(CoordinateNd left, CoordinateNd right) => left.Axes.Length == right.Axes.Length ? new CoordinateNd([..left.Axes.Zip(right.Axes, (l, r) => l - r)]) : throw new DimensionMismatchException(); public static CoordinateNd operator *(CoordinateNd coord, int amount) => new CoordinateNd([..coord.Axes.Select(a => a * amount)]); } public class DimensionMismatchException : Exception {}