Files
BuYuHouDuan/AdminSrc/AdminService/BeautifulNumber/BeautifulNumberGenerator.cs
T
2026-10-12 16:22:04 +08:00

221 lines
7.6 KiB
C#

namespace AdminService.BeautifulNumber;
public class BeautifulNumberGenerator
{
public static List<string> GenerateAllPossibleNumbersForRule(string rule)
{
var parts = ParseRuleIntoParts(rule);
int totalLength = parts.Sum(p => p.Length);
if (totalLength != 8)
{
string details = string.Join(", ", parts.Select(p => $"'{p.OriginalString}'({p.Type}, {p.Length}位)"));
throw new ArgumentException($"规则 '{rule}' 解析后的总长度为 {totalLength} 位,不符合要求的8位。详情: [{details}]");
}
var partCombinations = new List<List<string>>();
foreach (var part in parts)
{
partCombinations.Add(GenerateCombinationsForPart(part));
}
var finalNumbers = CartesianProduct(partCombinations);
return finalNumbers.Distinct().ToList();
}
private class RulePart
{
public string OriginalString { get; set; }
public PartType Type { get; set; }
public int Length { get; set; }
public string UniqueLetters { get; set; }
public bool HasPlaceholder { get; set; }
}
private enum PartType
{
Sequential,
FixedGroup, // K, T, KK, TT, KKT, TTKK etc.
Individual, // X
FixedNumber // 8888
}
private static List<RulePart> ParseRuleIntoParts(string rule)
{
var parts = new List<RulePart>();
int i = 0;
while (i < rule.Length)
{
char c = rule[i];
if (char.IsDigit(c))
{
int start = i;
while (i < rule.Length && char.IsDigit(rule[i])) i++;
parts.Add(new RulePart { OriginalString = rule.Substring(start, i - start), Type = PartType.FixedNumber, Length = i - start });
continue;
}
if (c >= 'A' && c <= 'H')
{
int start = i;
int direction = 0;
if (i + 1 < rule.Length && char.IsUpper(rule[i + 1]) && (rule[i + 1] >= 'A' && rule[i + 1] <= 'H'))
{
direction = rule[i + 1] > c ? 1 : -1;
i++;
while (i + 1 < rule.Length && char.IsUpper(rule[i + 1]) && (rule[i + 1] >= 'A' && rule[i + 1] <= 'H') && rule[i + 1] - rule[i] == direction)
{
i++;
}
}
bool hasPlaceholder = (i + 1 < rule.Length && rule[i + 1] == 'X');
if (hasPlaceholder) i++;
int sequenceLength = i - start + 1;
parts.Add(new RulePart { OriginalString = rule.Substring(start, sequenceLength), Type = PartType.Sequential, Length = sequenceLength, HasPlaceholder = hasPlaceholder });
i++;
continue;
}
if (c == 'X')
{
int start = i;
while (i < rule.Length && rule[i] == 'X') i++;
parts.Add(new RulePart { OriginalString = rule.Substring(start, i - start), Type = PartType.Individual, Length = i - start });
continue;
}
if (c == 'K' || c == 'T')
{
int start = i;
while (i < rule.Length && (rule[i] == 'K' || rule[i] == 'T')) i++;
string pattern = rule.Substring(start, i - start);
string uniqueLtrs = new string(pattern.Distinct().OrderBy(ch => ch).ToArray());
parts.Add(new RulePart { OriginalString = pattern, Type = PartType.FixedGroup, Length = pattern.Length, UniqueLetters = uniqueLtrs });
continue;
}
i++;
}
return parts;
}
private static List<string> GenerateCombinationsForPart(RulePart part)
{
switch (part.Type)
{
case PartType.Sequential:
return GenerateSequentialNumbersWithPlaceholder(part.OriginalString, part.HasPlaceholder);
case PartType.FixedGroup:
return GenerateFixedGroupNumbers(part.OriginalString, part.UniqueLetters);
case PartType.Individual:
return GenerateIndividualNumbers(part.OriginalString.Length);
case PartType.FixedNumber:
return new List<string> { part.OriginalString };
default:
return new List<string>();
}
}
private static List<string> GenerateSequentialNumbersWithPlaceholder(string seqRule, bool hasPlaceholder)
{
string sequenceRule = hasPlaceholder ? seqRule.Substring(0, seqRule.Length - 1) : seqRule;
int length = sequenceRule.Length;
if (length == 0) return new List<string> { "" };
var baseSequences = new List<string>();
bool isAscending = length > 1 && sequenceRule[1] > sequenceRule[0];
if (isAscending)
{
int maxStart = 10 - length;
for (int start = 0; start <= maxStart; start++)
{
string num = "";
for (int i = 0; i < length; i++) num += (start + i).ToString();
baseSequences.Add(num);
}
}
else
{
int minStart = length - 1;
for (int start = 9; start >= minStart; start--)
{
string num = "";
for (int i = 0; i < length; i++) num += (start - i).ToString();
baseSequences.Add(num);
}
}
if (!hasPlaceholder)
{
return baseSequences;
}
var finalSequences = new List<string>();
var digits = new List<string> { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
foreach (var seq in baseSequences)
{
foreach (var digit in digits)
{
finalSequences.Add(seq + digit);
}
}
return finalSequences;
}
private static List<string> GenerateFixedGroupNumbers(string pattern, string uniqueLetters)
{
var allCombinations = new List<List<string>>();
foreach (char letter in uniqueLetters)
{
var letterValues = new List<string>();
for (int i = 0; i < 10; i++) letterValues.Add(i.ToString());
allCombinations.Add(letterValues);
}
var letterAssignments = CartesianProduct(allCombinations);
var results = new List<string>();
foreach (var assignment in letterAssignments)
{
var map = new Dictionary<char, string>();
for (int i = 0; i < uniqueLetters.Length; i++)
{
map[uniqueLetters[i]] = assignment[i].ToString();
}
string number = "";
foreach (char c in pattern)
{
number += map[c];
}
results.Add(number);
}
return results;
}
private static List<string> GenerateIndividualNumbers(int length)
{
var allCombinations = new List<List<string>>();
for (int i = 0; i < length; i++)
{
var digitList = new List<string>();
for (int j = 0; j < 10; j++) digitList.Add(j.ToString());
allCombinations.Add(digitList);
}
return CartesianProduct(allCombinations);
}
private static List<string> CartesianProduct(List<List<string>> listOfLists)
{
IEnumerable<string> result = new[] { "" };
foreach (var list in listOfLists)
{
result = from r in result
from l in list
select r + l;
}
return result.ToList();
}
}