my advent of code solutions
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}