#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;
}