my advent of code solutions
at main 109 lines 3.1 kB view raw
1namespace Solutions; 2 3public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TKey : notnull 4{ 5 public TValue? DefaultValue; 6 7 public new TValue? this[TKey key] 8 { 9 get => TryGetValue(key, out var t) ? t : DefaultValue; 10 set 11 { 12 if (value != null) base[key] = value; 13 } 14 } 15} 16 17public class Tree<T>(Tree<T>.Node root) 18{ 19 public class Node(Node? parent, T data) 20 { 21 public Node? Parent { get; private set; } = parent; 22 public T Data { get; set; } = data; 23 private List<Node?> Children { get; } = []; 24 25 public Node? Left 26 { 27 get => Children.Count >= 1 ? Children[0] : null; 28 29 set 30 { 31 if (value != null) value.Parent = this; 32 if (Children.Count >= 1) Children[0] = value; 33 else Children.Add(value); 34 } 35 } 36 37 public Node? Right 38 { 39 get => Children.Count >= 2 ? Children[1] : null; 40 41 set 42 { 43 if (value != null) value.Parent = this; 44 switch (Children.Count) 45 { 46 case >= 2: 47 Children[1] = value; 48 break; 49 case 0: 50 Children.Add(null); 51 break; 52 } 53 Children.Add(value); 54 } 55 } 56 57 public int DistanceToParent(Node nodeParent) 58 { 59 var current = this; 60 var dist = 0; 61 while (current != nodeParent) 62 { 63 dist++; 64 current = current?.Parent; 65 } 66 67 return dist; 68 } 69 } 70 71 public Node Root { get; } = root; 72} 73 74public class Dijkstra<TCell, TMid> where TCell : notnull 75{ 76 public Func<TCell, IEnumerable<TMid>>? Neighbors; 77 public Func<TMid, int>? Distance; 78 public Func<TCell, TMid, TCell>? Cell; 79 80 public int ComputeFind(TCell start, TCell target, Func<TCell, bool>? valid = null) 81 { 82 valid ??= _ => true; 83 var dist = new DefaultDictionary<TCell, int> { DefaultValue = int.MaxValue, [start] = 0 }; 84 var seen = new HashSet<TCell>(); 85 var queue = new PriorityQueue<TCell, int>(); 86 queue.Enqueue(start, 0); 87 while (queue.Count > 0) 88 { 89 var cell = queue.Dequeue(); 90 if (seen.Contains(cell)) continue; 91 var current = dist[cell]; 92 if (Equals(cell, target)) return current; 93 seen.Add(cell); 94 foreach (var neighbor in Neighbors!(cell)) 95 { 96 var other = Cell!(cell, neighbor); 97 if (!valid(other)) continue; 98 var weight = Distance!(neighbor); 99 if (!seen.Contains(other)) queue.Enqueue(other, current + weight); 100 if (current + weight < dist[other]) 101 { 102 dist[other] = current + weight; 103 } 104 } 105 } 106 107 return -1; 108 } 109}