games0802

AoC Day8

Jan 12th, 2026
94
0
164 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.79 KB | Source Code | 0 0
  1. using System.Diagnostics;
  2. using System.Numerics;
  3. using System.Runtime.Serialization;
  4. using System.Security.Cryptography;
  5. using static System.Runtime.InteropServices.JavaScript.JSType;
  6.  
  7. namespace Day8
  8. {
  9.     internal class Program
  10.     {
  11.         private static List<List<Point>> circuitList = new();
  12.  
  13.         static void Main(string[] args)
  14.         {
  15.             const string input_filename = "day8_input.txt";
  16.             Debug.Assert(File.Exists(input_filename));
  17.  
  18.             string[] input_lines = File.ReadAllLines(input_filename);
  19.             Debug.Assert(input_lines.Length > 0);
  20.  
  21.             // convert the input lines into Points
  22.             List<Point> points = new();
  23.  
  24.             bool part1 = false;
  25.  
  26.             foreach (string input in input_lines)
  27.             {
  28.                 string[] coords = input.Split(',');
  29.                 Debug.Assert(coords.Length == 3);
  30.  
  31.                 Debug.Assert(long.TryParse(coords[0], out long x));
  32.                 Debug.Assert(long.TryParse(coords[1], out long y));
  33.                 Debug.Assert(long.TryParse(coords[2], out long z));
  34.  
  35.                 points.Add(new Point(x, y, z));
  36.             }
  37.  
  38.             // Now that we have a list of the points, we need to find the shortest distance between them
  39.             // To do this, we will need to loop through the list (not quite n^2) to do all of the comparisons
  40.             // We will keep the comparisons in a sorted Dictionary with a reference to the points involved
  41.             Dictionary<PointDistanceKey, long> distanceList = new();
  42.  
  43.             for (int i = 0; i < points.Count; i++)
  44.             {
  45.                 for (int j = i + 1; j < points.Count; j++)
  46.                 {
  47.                     distanceList.Add(new PointDistanceKey(points[i], points[j]), points[i].DistanceSquared(points[j]));
  48.                 }
  49.             }
  50.  
  51.             // Now sort the list
  52.             var sortedDistanceList = distanceList.OrderBy(i => i.Key).ToDictionary();
  53.  
  54.             // Now that we have a sorted list of the distance between all of the points, we need to assemble
  55.             // circuits of them.
  56.  
  57.             int count = 0;
  58.             foreach (PointDistanceKey key in sortedDistanceList.Keys)
  59.             {
  60.                 count++;
  61.                 List<Point>? p1_circuit = FindCircuitContainingPoint(key.P1);
  62.                 List<Point>? p2_circuit = FindCircuitContainingPoint(key.P2);
  63.  
  64.                 // if neither point is in a circuit, then start a new one
  65.                 if (p1_circuit == null && p2_circuit == null)
  66.                 {
  67.                     circuitList.Add(new List<Point> { key.P1, key.P2 });
  68.                 }
  69.                 else if (p1_circuit == null && p2_circuit != null) // Add p1 to p2_circuit
  70.                 {
  71.                     p2_circuit.Add(key.P1);
  72.                 }
  73.                 else if (p1_circuit != null && p2_circuit == null) // Add p2 to p1_circuit
  74.                 {
  75.                     p1_circuit.Add(key.P2);
  76.                 }
  77.                 else if (p1_circuit != p2_circuit)  // we know (p1_circuit != null && p2_circuit != null)
  78.                 {
  79.                     // we need to combine the circuits
  80.                     p1_circuit.AddRange(p2_circuit);
  81.                     circuitList.Remove(p2_circuit);
  82.                 }
  83.  
  84.  
  85.                 if (part1)
  86.                 {
  87.                     if (count == 1000)
  88.                     {
  89.                         long product = MultiplyLargestThreeCounts(circuitList);
  90.                         Console.WriteLine("Product of largest 3 circuits: " + product);
  91.                         break;
  92.                     }
  93.                 }
  94.                 else
  95.                 {
  96.                     if (circuitList.Count == 1 && circuitList[0].Count == input_lines.Length)
  97.                     {
  98.                         Console.WriteLine("Last Points X = " + key.P1.X + " and " + key.P2.X + " (multiplied = " +(key.P1.X * key.P2.X) + ")");
  99.                         break;
  100.                     }
  101.                 }
  102.             }
  103.         }
  104.  
  105.         public static long MultiplyLargestThreeCounts<T>(List<List<T>> collections)
  106.         {
  107.             // 1. Get the count of each collection.
  108.             IEnumerable<int> counts = collections.Select(c => c.Count);
  109.  
  110.             // 2. Order the counts in descending order.
  111.             var sortedCountsDesc = counts.OrderByDescending(count => count);
  112.  
  113.             // 3. Take the top 3 counts.
  114.             var topThreeCounts = sortedCountsDesc.Take(3);
  115.  
  116.             // 4. Multiply the three counts together using the Aggregate function.
  117.             //    We use an initial seed of 1 for multiplication.
  118.             //    Using 'long' to prevent potential overflow with large counts.
  119.             long product = topThreeCounts.Aggregate(1L, (currentProduct, count) => currentProduct * count);
  120.  
  121.             return product;
  122.         }
  123.  
  124.         static List<Point>? FindCircuitContainingPoint(Point p)
  125.         {
  126.             foreach (List<Point> circuit in circuitList)
  127.             {
  128.                 if (circuit.Contains(p)) return circuit;
  129.             }
  130.  
  131.             return null;
  132.         }
  133.     }
  134.  
  135.     internal class PointDistanceKey : IComparable<PointDistanceKey>
  136.     {
  137.         public Point P1;
  138.         public Point P2;
  139.  
  140.         public PointDistanceKey(Point p1, Point p2)
  141.         {
  142.             P1 = p1;
  143.             P2 = p2;
  144.         }
  145.  
  146.         public int CompareTo(PointDistanceKey? other)
  147.         {
  148.             if (other == null) return 1; // Current instance is greater than a null object
  149.  
  150.             // Default sort by the Distance between the Points
  151.             // The int returned by CompareTo determines the relative order:
  152.             // > 0 means current object comes after 'other'
  153.             // < 0 means current object comes before 'other'
  154.             //   0 means they are equal in sort order
  155.  
  156.             double local_d2 = P1.DistanceSquared(P2);
  157.             double other_d2 = other.P1.DistanceSquared( other.P2);
  158.             if (local_d2 == other_d2)
  159.                 return 0;
  160.             if (local_d2 < other_d2)
  161.                 return -1;
  162.             else
  163.                 return 1; // if (local_d2 > other_d2)
  164.         }
  165.  
  166.         public override string ToString()
  167.         {
  168.             return P1.ToString()+":"+P2.ToString();
  169.         }
  170.     }
  171.  
  172.     internal class Point
  173.     {
  174.         public long X;
  175.         public long Y;
  176.         public long Z;
  177.  
  178.         public Point(long x, long y, long z)
  179.         {
  180.             X = x;
  181.             Y = y;
  182.             Z = z;
  183.         }
  184.  
  185.         public long DistanceSquared(Point p2)
  186.         {
  187.             return (p2.X - X) * (p2.X - X) + (p2.Y - Y) * (p2.Y - Y) + (p2.Z - Z) * (p2.Z - Z);
  188.         }
  189.  
  190.         public override string ToString()
  191.         {
  192.             return X+","+Y+","+Z;
  193.         }
  194.     }
  195. }
Tags: AoC Day8
Advertisement
Add Comment
Please, Sign In to add comment