AoC12
unknown
csharp
4 years ago
4.1 kB
12
Indexable
class AoC12 : AdventOfCode { readonly Dictionary<string, Location> _locations = new Dictionary<string, Location>(); Location _start; public override void Start() { _start = BuildCaveMap(); } public override void Run1() { Run(false); } public override void Run2() { Run(true); } void Run(bool allowDouble) { LocationMapper mapper = new LocationMapper(allowDouble); var pathes = mapper.Map(_start); for (int i = 0; i < pathes.Count; i++) WriteLine(pathes[i].ToString(',')); WriteLine($"Number of path found:{pathes.Count}"); } Location BuildCaveMap() { for (int i = 0; i < inputFile.Length; i++) { var caves = inputFile[i].Split('-'); var c1 = GetCave(caves[0]); var c2 = GetCave(caves[1]); c1.Connection.Add(c2); c2.Connection.Add(c1); } foreach(var kvp in _locations) kvp.Value.Connection.Sort((l1, l2) => string.Compare(l1.Name, l2.Name, StringComparison.Ordinal)); return _locations["start"]; } Location GetCave(string name) { if (!_locations.TryGetValue(name, out var loc)) _locations[name] = loc = new Location(name); return loc; } class Location { public Location(string name) { Name = name; IsLarge = char.IsUpper(name[0]); IsEnd = name == "end"; IsStart = name == "start"; } public readonly string Name; public override string ToString() => Name; public readonly List<Location> Connection = new List<Location>(); public readonly bool IsLarge; public readonly bool IsEnd; public readonly bool IsStart; public int Length => Connection.Count; public Location this[int key] => Connection[key]; } class LocationMapper { public LocationMapper(bool allowOnceDouble = false) => _allowOnceDouble = allowOnceDouble; readonly Stack<Location> _currentPath = new Stack<Location>(); readonly List<List<Location>> _pathFound = new List<List<Location>>(); readonly bool _allowOnceDouble; public List<List<Location>> Map(in Location start) { _pathFound.Clear(); for (int i = 0; i < start.Length; i++) ExpandStart(start, i); return _pathFound; } void ExpandStart(in Location start, int index) { _currentPath.Clear(); _currentPath.Push(start); Expand(start[index]); } Location _doubleNode; bool TryExpand(in Location node) { if (node.IsStart) return false; if (node.IsEnd || node.IsLarge) return true; bool exists = _currentPath.Contains(node); if (!exists) return true; if (!_allowOnceDouble || _doubleNode != null) return false; _doubleNode = node; return true; } void Expand(Location node) { if (node.IsEnd) { AddPath(node); return; } _currentPath.Push(node); for (int i = 0; i < node.Length; i++) if (TryExpand(node[i])) Expand(node[i]); _currentPath.Pop(); if (node == _doubleNode) _doubleNode = null; } readonly Stack<Location> _reversePath = new Stack<Location>(); void AddPath(Location end) { List<Location> path = new List<Location>(); _reversePath.Clear(); foreach (var l in _currentPath) _reversePath.Push(l); path.AddRange(_reversePath); path.Add(end); _pathFound.Add(path); } } }
Editor is loading...