0102030405060708

Advent of Code

2025/8

Playground

in C#

by encse

Equipped with a new understanding of teleporter maintenance, you confidently step onto the repaired teleporter pad.

You rematerialize on an unfamiliar teleporter pad and find yourself in a vast underground space which contains a giant playground!

Visit the website for the full story and full puzzle description.

I decided to go with two implementations of Kruskal's algorithm, as part one and two are different enough. I didn't use a disjoint set representation. It's fast enough this way as well, and switching to disjoint sets would just make the code longer.

namespace AdventOfCode.Y2025.Day08;

using System.Collections.Generic;
using System.Data;
using System.Linq;

record Point(decimal x, decimal y, decimal z);

[ProblemName("Playground")]
class Solution : Solver {

    public object PartOne(string input) {
        // Apply 1000 steps of Kruskal's algorithm to the points using the specified
        // metric, then return the product of the sizes of the three largest components.
        var points = Parse(input);
        var setOf = points.ToDictionary(p => p, p => new HashSet<Point>([p]));
        foreach (var (a, b) in GetOrderedPairs(points).Take(1000)) {
            if (setOf[a] != setOf[b]) {
                Connect(a, b, setOf);
            }
        }
        return setOf.Values.Distinct()
            .OrderByDescending(set => set.Count)
            .Take(3)
            .Aggregate(1, (a, b) => a * b.Count);
    }

    public object PartTwo(string input) {
        // Run Kruskal's algorithm on all points and return the product of the
        // x-coordinates of the last edge added to the spanning tree.
        var points = Parse(input);
        var componentCount = points.Length;
        var setOf = points.ToDictionary(p => p, p => new HashSet<Point>([p]));
        var res = 0m;
        foreach (var (a, b) in GetOrderedPairs(points).TakeWhile(_ => componentCount > 1)) {
            if (setOf[a] != setOf[b]) {
                Connect(a, b, setOf);
                res = a.x * b.x;
                componentCount--;
            }
        }
        return res;
    }

    void Connect(Point a, Point b, Dictionary<Point, HashSet<Point>> setOf) {
        setOf[a].UnionWith(setOf[b]);
        foreach (var p in setOf[b]) {
            setOf[p] = setOf[a];
        }
    }

    IEnumerable<(Point a, Point b)> GetOrderedPairs(Point[] points) =>
        from a in points
        from b in points
        where (a.x, a.y, a.z).CompareTo((b.x, b.y, b.z)) < 0
        orderby Metric(a,b)
        select (a, b);

    decimal Metric(Point a, Point b) =>
        (a.x - b.x) * (a.x - b.x) +
        (a.y - b.y) * (a.y - b.y) +
        (a.z - b.z) * (a.z - b.z);

    Point[] Parse(string input) => (
        from line in input.Split("\n")
        let parts = line.Split(",").Select(int.Parse).ToArray()
        select new Point(parts[0], parts[1], parts[2])
    ).ToArray();
}

Please ☆ my repo if you like it!

© 2025 | Advent of Code is a registered trademark in the US | Images provided by Bing and Nano Banana