AoC12 Perf

mail@pastecode.io avatar
unknown
csharp
2 years ago
3.1 kB
2
Indexable
Never
class AoC12 : AdventOfCode
{
    Cave _start;
    public override void Start() { _start = BuildCaveMap(); }
    public override void Run1() { }
    public override void Run2() { Run(); }
    void Run()
    {
        var sw = Stopwatch.StartNew();
        SpecialCaveMapper mapper = new SpecialCaveMapper();
        int pathCount = mapper.Map(_start);
        sw.Stop();
        WriteLine($"Number of path found:{pathCount} in {sw.Elapsed.TotalMilliseconds}ms");
    }
    Cave BuildCaveMap()
    {
        Dictionary<string, Cave> locations = new Dictionary<string, Cave>();
        for (int i = 0; i < inputFile.Length; i++)
        {
            var caves = inputFile[i].Split('-');
            if (!locations.TryGetValue(caves[0], out var c1))
                locations[caves[0]] = c1 = new Cave(caves[0]);
            if (!locations.TryGetValue(caves[1], out var c2))
                locations[caves[1]] = c2 = new Cave(caves[1]);
            c1.Add(c2);
            c2.Add(c1);
        }
        return locations["start"];
    }
    class Cave
    {
        public Cave(string name)
        {
            _id = name.GetHashCode();
            IsLarge = char.IsUpper(name[0]);
            IsEnd = name == "end";
            IsStart = name == "start";
        }
        public readonly bool IsLarge;
        public readonly bool IsEnd;
        public readonly bool IsStart;

        readonly int _id;
        public override int GetHashCode()=>_id.GetHashCode();

        Cave[] _connection = new Cave[0];
        public void Add(Cave c)
        {
            Array.Resize(ref _connection, _connection.Length + 1);
            _connection[_connection.Length - 1] = c;
        }
        public int Length => _connection.Length;
        public Cave this[int key] => _connection[key];

        public int VisitCount;
    }
    class SpecialCaveMapper
    {
        int _pathFound;
        public int Map(in Cave start)
        {
            _pathFound = 0;
            for (int i = 0; i < start.Length; i++)
                ExpandStart(start, i);
            return _pathFound;
        }
        void ExpandStart(in Cave start, int index)
        {
            Expand(start[index]);
        }

        Cave _doubleNode;
        bool TryExpand(in Cave node)
        {
            if (node.IsEnd)
            {
                ++_pathFound;
                return false;
            }
            if (node.IsStart)
                return false;
            if (node.IsLarge)
                return true;

            bool exists = node.VisitCount > 0;
            if (!exists) return true;
            if (_doubleNode != null) return false;
            _doubleNode = node;
            return true;
        }
        void Expand(Cave node)
        {
            ++node.VisitCount;
            for (int i = 0; i < node.Length; i++)
                if (TryExpand(node[i]))
                    Expand(node[i]);
            --node.VisitCount;
            if (node == _doubleNode)
                _doubleNode = null;
        }
    }
}