using System; using System.Collections.Generic; using System.Linq; public static class Kata { private class Graph { private struct Edge { public char Through { get; set; } public char To { get; set; } }; public static readonly char NO_CONDITION = '\0'; private Dictionary> edges = new Dictionary>(); private HashSet visited = new HashSet(); private Graph addEdge(char src, char through, char dst) { var newEdge = new Edge { Through = through, To = dst }; if (edges.TryGetValue(src, out var lst)) { lst.Add(newEdge); } else { edges.Add(src, new List() { newEdge }); } return this; } public Graph AddDirectEdge(char src, char dst) => addEdge(src, NO_CONDITION, dst); public Graph AddIndirectEdge(char src, char through, char dst) => addEdge(src, through, dst); public Graph AddBiDirectEdge(char src, char dst) => AddBiIndirectEdge(src, NO_CONDITION, dst); public Graph AddBiIndirectEdge(char src, char through, char dst) => addEdge(src, through, dst) .addEdge(dst, through, src); public void ResetVisited() => visited.Clear(); public bool BeenVisited(char vertex) => visited.Contains(vertex); public void Mark(char vertex) => visited.Add(vertex); public void Unmark(char vertex) => visited.Remove(vertex); public bool HasEdge(char fromVertex, char toVertex) => edges[fromVertex].Any(e => e.To == toVertex && (e.Through == NO_CONDITION || BeenVisited(e.Through))); public Graph AddMultipleBiDirectEdges(char fromVertex, string toVertices) { foreach (var toVertex in toVertices) { AddBiDirectEdge(fromVertex, toVertex); } return this; } } private static Graph g = new Graph() .AddMultipleBiDirectEdges('A', "BDEFH").AddMultipleBiDirectEdges('B', "CDEFGI") .AddMultipleBiDirectEdges('C', "DEFH").AddMultipleBiDirectEdges('D', "EGHI") .AddMultipleBiDirectEdges('E', "FGHI").AddMultipleBiDirectEdges('F', "GHI") .AddMultipleBiDirectEdges('G', "H").AddMultipleBiDirectEdges('H', "I") .AddBiIndirectEdge('A', 'B', 'C').AddBiIndirectEdge('A', 'D', 'G').AddBiIndirectEdge('A', 'E', 'I') .AddBiIndirectEdge('B', 'E', 'H').AddBiIndirectEdge('C', 'E', 'G').AddBiIndirectEdge('C', 'F', 'I') .AddBiIndirectEdge('D', 'E', 'F').AddBiIndirectEdge('G', 'H', 'I'); public static int CountPatternsFrom(char firstDot, int length) { if (length <= 0 || length >= 10) { return 0; } if (length == 1) { return 1; } int total = 0; g.Mark(firstDot); foreach (var vertex in "ABCDEFGHI") { if (!g.BeenVisited(vertex) && g.HasEdge(firstDot, vertex)) { total += CountPatternsFrom(vertex, length - 1); } } g.Unmark(firstDot); return total; } }