01020304050607080910111213141516171819202122232425

Advent of Code

2022/23

Unstable Diffusion

in C#

by encse

You enter a large crater of gray dirt where the grove is supposed to be. All around you, plants you imagine were expected to be full of fruit are instead withered and broken. A large group of Elves has formed in the middle of the grove.

"...but this volcano has been dormant for months. Without ash, the fruit can't grow!"

Read the full puzzle.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace AdventOfCode.Y2022.Day23;

[ProblemName("Unstable Diffusion")]
class Solution : Solver {

    // I used complex numbers for a change. The map is represented with a hashset of positions.

    public object PartOne(string input) 
        => Simulate(Parse(input)).Select(Area).ElementAt(9);

    public object PartTwo(string input) 
        => Simulate(Parse(input)).Count();

    IEnumerable<HashSet<Complex>> Simulate(HashSet<Complex> elves) {
        var lookAround = new Queue<Complex>(new []{ N, S, W, E });

        for (var fixpoint = false; !fixpoint; lookAround.Enqueue(lookAround.Dequeue())) {
           
            // 1) collect proposals; for each position (key) compute the list of the elves 
            //    who want to step there
            var proposals = new Dictionary<Complex, List<Complex>>();

            foreach (var elf in elves) {
                var lonely = Directions.All(dir => !elves.Contains(elf + dir));
                if (lonely) {
                    continue;
                }

                foreach (var dir in lookAround) {
                    
                    // elf proposes a postion if nobody stands in that direction
                    var proposes = ExtendDir(dir).All(d => !elves.Contains(elf + d));
                    if (proposes) {
                        var pos = elf + dir;
                        if (!proposals.ContainsKey(pos)) {
                            proposals[pos] = new List<Complex>();
                        }
                        proposals[pos].Add(elf);
                        break;
                    }
                }
            }

            // 2) move elves, compute fixpoint flag
            fixpoint = true;
            foreach (var p in proposals) {
                var (to, from) = p;
                if (from.Count == 1) {
                    elves.Remove(from.Single());
                    elves.Add(to);
                    fixpoint = false;
                }
            }

            yield return elves;
        }
    }

    double Area(HashSet<Complex> elves) {
        // smallest enclosing rectangle
        var width = elves.Select(p => p.Real).Max() - 
                    elves.Select(p => p.Real).Min() + 1;

        var height = elves.Select(p => p.Imaginary).Max() - 
                     elves.Select(p => p.Imaginary).Min() + 1;

        return width * height - elves.Count;
    }
     
    HashSet<Complex> Parse(string input) {
        var lines = input.Split("\n");
        return (
            from irow in Enumerable.Range(0, lines.Length)
            from icol in Enumerable.Range(0, lines[0].Length)
            where lines[irow][icol] == '#'
            select new Complex(icol, irow)
        ).ToHashSet();
    }

    ///  -------

    static Complex N = new Complex(0, -1);
    static Complex E = new Complex(1, 0);
    static Complex S = new Complex(0, 1);
    static Complex W = new Complex(-1, 0);
    static Complex NW = N + W;
    static Complex NE = N + E;
    static Complex SE = S + E;
    static Complex SW = S + W;

    static Complex[] Directions = new[] { NW, N, NE, E, SE, S, SW, W };

    // Extends an ordinal position with its intercardinal neighbours
    Complex[] ExtendDir(Complex dir) =>
        dir == N ? new[] { NW, N, NE } :
        dir == E ? new[] { NE, E, SE } :
        dir == S ? new[] { SW, S, SE } :
        dir == W ? new[] { NW, W, SW } :
                   throw new Exception();

}

Please ☆ my repo if you like it!

© 2025 Advent of Code is a registered trademark in the US Images provided by Bing image creator