#pragma warning disable List<(string operand, string target, string other)> originalSteps = new(); List<long> addX = new(); List<long> divZ = new(); List<long> addY = new(); List<long> maxValOnStep = new(); Dictionary<(int groupNum, long prevZ), List<string>> cacheDic = new(); List<string> validIDs; var lines = File.ReadAllText("../../../../Input.in").Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) .Where(s => false || !string.IsNullOrWhiteSpace(s)) .Select(s => true ? s.Trim() : s) .ToList(); for (int i = 0; i < 14; i++) { divZ.Add(int.Parse(lines[(18 * i) + 4].Split()[2])); addX.Add(int.Parse(lines[(18 * i) + 5].Split()[2])); addY.Add(int.Parse(lines[(18 * i) + 15].Split()[2])); } for (int i = 0; i < divZ.Count; i++) { maxValOnStep.Add(divZ.Skip(i).Aggregate(1L, (a, b) => a * b)); } validIDs = RecursiveSearch(0, 0).ToList(); validIDs.Sort(); Console.WriteLine("The biggest valid number is " + validIDs.Last()); Console.WriteLine("The smallest valid number is " + validIDs.First()); long RunGroup(int groupNum, long prevZ, long input) { long z = prevZ; long x = addX[groupNum] + z % 26; z /= divZ[groupNum]; if (x != input) { z *= 26; z += input + addY[groupNum]; } return z; } List<string> RecursiveSearch(int groupNum, long prevZ) { if (cacheDic.ContainsKey((groupNum, prevZ))) { return cacheDic[(groupNum, prevZ)]; } if (groupNum >= 14) { if (prevZ == 0) return new() { "" }; return null; } if (prevZ > maxValOnStep[groupNum]) { return null; } List<string> res = new(); long nextX = addX[groupNum] + prevZ % 26; List<string> nextStrings; long nextZ; if (0 < nextX && nextX < 10) { nextZ = RunGroup(groupNum, prevZ, nextX); nextStrings = RecursiveSearch(groupNum + 1, nextZ); if (null != nextStrings) { foreach (var s in nextStrings) { res.Add($"{nextX}{s}"); } } } else { foreach (int i in Enumerable.Range(1, 9)) { nextZ = RunGroup(groupNum, prevZ, i); nextStrings = RecursiveSearch(groupNum + 1, nextZ); if (null != nextStrings) { foreach (var s in nextStrings) { res.Add($"{i}{s}"); } } } } cacheDic[(groupNum, prevZ)] = res; return res; }